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 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
625 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
626 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
627 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
628 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
629 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
632 "#ifdef USESATURATION\n"
633 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
634 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
635 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
636 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
639 "#ifdef USEGAMMARAMPS\n"
640 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
641 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
642 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
646 "#else // !MODE_POSTPROCESS\n"
651 "#ifdef MODE_GENERIC\n"
652 "#ifdef USEDIFFUSE\n"
653 "varying vec2 TexCoord1;\n"
655 "#ifdef USESPECULAR\n"
656 "varying vec2 TexCoord2;\n"
658 "#ifdef VERTEX_SHADER\n"
661 " gl_FrontColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
665 "#ifdef USESPECULAR\n"
666 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
668 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
672 "#ifdef FRAGMENT_SHADER\n"
673 "#ifdef USEDIFFUSE\n"
674 "uniform sampler2D Texture_First;\n"
676 "#ifdef USESPECULAR\n"
677 "uniform sampler2D Texture_Second;\n"
682 " gl_FragColor = gl_Color;\n"
683 "#ifdef USEDIFFUSE\n"
684 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
687 "#ifdef USESPECULAR\n"
688 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
689 "# ifdef USECOLORMAPPING\n"
690 " gl_FragColor *= tex2;\n"
693 " gl_FragColor += tex2;\n"
695 "# ifdef USEVERTEXTEXTUREBLEND\n"
696 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
701 "#else // !MODE_GENERIC\n"
706 "#ifdef MODE_BLOOMBLUR\n"
707 "varying TexCoord;\n"
708 "#ifdef VERTEX_SHADER\n"
711 " gl_FrontColor = gl_Color;\n"
712 " TexCoord = gl_MultiTexCoord0.xy;\n"
713 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
717 "#ifdef FRAGMENT_SHADER\n"
718 "uniform sampler2D Texture_First;\n"
719 "uniform vec4 BloomBlur_Parameters;\n"
724 " vec2 tc = TexCoord;\n"
725 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
726 " tc += BloomBlur_Parameters.xy;\n"
727 " for (i = 1;i < SAMPLES;i++)\n"
729 " color += texture2D(Texture_First, tc).rgb;\n"
730 " tc += BloomBlur_Parameters.xy;\n"
732 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
735 "#else // !MODE_BLOOMBLUR\n"
736 "#ifdef MODE_REFRACTION\n"
737 "varying vec2 TexCoord;\n"
738 "varying vec4 ModelViewProjectionPosition;\n"
739 "uniform mat4 TexMatrix;\n"
740 "#ifdef VERTEX_SHADER\n"
744 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
745 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
746 " ModelViewProjectionPosition = gl_Position;\n"
750 "#ifdef FRAGMENT_SHADER\n"
751 "uniform sampler2D Texture_Normal;\n"
752 "uniform sampler2D Texture_Refraction;\n"
753 "uniform sampler2D Texture_Reflection;\n"
755 "uniform vec4 DistortScaleRefractReflect;\n"
756 "uniform vec4 ScreenScaleRefractReflect;\n"
757 "uniform vec4 ScreenCenterRefractReflect;\n"
758 "uniform vec4 RefractColor;\n"
759 "uniform vec4 ReflectColor;\n"
760 "uniform float ReflectFactor;\n"
761 "uniform float ReflectOffset;\n"
765 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
766 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
768 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
769 " // FIXME temporary hack to detect the case that the reflection\n"
770 " // gets blackened at edges due to leaving the area that contains actual\n"
772 " // Remove this 'ack once we have a better way to stop this thing from\n"
774 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
775 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
776 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
777 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
778 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
779 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
782 "#else // !MODE_REFRACTION\n"
787 "#ifdef MODE_WATER\n"
788 "varying vec2 TexCoord;\n"
789 "varying vec3 EyeVector;\n"
790 "varying vec4 ModelViewProjectionPosition;\n"
791 "#ifdef VERTEX_SHADER\n"
792 "uniform vec3 EyePosition;\n"
793 "uniform mat4 TexMatrix;\n"
797 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
798 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
799 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
800 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
801 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
802 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
803 " ModelViewProjectionPosition = gl_Position;\n"
807 "#ifdef FRAGMENT_SHADER\n"
808 "uniform sampler2D Texture_Normal;\n"
809 "uniform sampler2D Texture_Refraction;\n"
810 "uniform sampler2D Texture_Reflection;\n"
812 "uniform vec4 DistortScaleRefractReflect;\n"
813 "uniform vec4 ScreenScaleRefractReflect;\n"
814 "uniform vec4 ScreenCenterRefractReflect;\n"
815 "uniform vec4 RefractColor;\n"
816 "uniform vec4 ReflectColor;\n"
817 "uniform float ReflectFactor;\n"
818 "uniform float ReflectOffset;\n"
822 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
823 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
825 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
826 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
827 " // FIXME temporary hack to detect the case that the reflection\n"
828 " // gets blackened at edges due to leaving the area that contains actual\n"
830 " // Remove this 'ack once we have a better way to stop this thing from\n"
832 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
833 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
834 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
835 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
836 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
837 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
838 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
839 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
840 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
841 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
842 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
843 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
846 "#else // !MODE_WATER\n"
851 "// common definitions between vertex shader and fragment shader:\n"
853 "varying vec2 TexCoord;\n"
854 "#ifdef USEVERTEXTEXTUREBLEND\n"
855 "varying vec2 TexCoord2;\n"
857 "#ifdef USELIGHTMAP\n"
858 "varying vec2 TexCoordLightmap;\n"
861 "#ifdef MODE_LIGHTSOURCE\n"
862 "varying vec3 CubeVector;\n"
865 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
866 "varying vec3 LightVector;\n"
869 "#ifdef USEEYEVECTOR\n"
870 "varying vec3 EyeVector;\n"
873 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
877 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
878 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
879 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
882 "#ifdef USEREFLECTION\n"
883 "varying vec4 ModelViewProjectionPosition;\n"
885 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
886 "uniform vec3 LightPosition;\n"
887 "varying vec4 ModelViewPosition;\n"
890 "#ifdef MODE_LIGHTSOURCE\n"
891 "uniform vec3 LightPosition;\n"
893 "uniform vec3 EyePosition;\n"
894 "#ifdef MODE_LIGHTDIRECTION\n"
895 "uniform vec3 LightDir;\n"
897 "uniform vec4 FogPlane;\n"
899 "#ifdef USESHADOWMAPORTHO\n"
900 "varying vec3 ShadowMapTC;\n"
907 "// 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"
909 "// fragment shader specific:\n"
910 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Color;\n"
914 "uniform sampler2D Texture_Gloss;\n"
916 "uniform sampler2D Texture_Glow;\n"
918 "#ifdef USEVERTEXTEXTUREBLEND\n"
919 "uniform sampler2D Texture_SecondaryNormal;\n"
920 "uniform sampler2D Texture_SecondaryColor;\n"
921 "uniform sampler2D Texture_SecondaryGloss;\n"
923 "uniform sampler2D Texture_SecondaryGlow;\n"
926 "#ifdef USECOLORMAPPING\n"
927 "uniform sampler2D Texture_Pants;\n"
928 "uniform sampler2D Texture_Shirt;\n"
931 "uniform sampler2D Texture_FogMask;\n"
933 "#ifdef USELIGHTMAP\n"
934 "uniform sampler2D Texture_Lightmap;\n"
936 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
937 "uniform sampler2D Texture_Deluxemap;\n"
939 "#ifdef USEREFLECTION\n"
940 "uniform sampler2D Texture_Reflection;\n"
943 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
944 "uniform sampler2D Texture_ScreenDepth;\n"
945 "uniform sampler2D Texture_ScreenNormalMap;\n"
947 "#ifdef USEDEFERREDLIGHTMAP\n"
948 "uniform sampler2D Texture_ScreenDiffuse;\n"
949 "uniform sampler2D Texture_ScreenSpecular;\n"
952 "uniform myhalf3 Color_Pants;\n"
953 "uniform myhalf3 Color_Shirt;\n"
954 "uniform myhalf3 FogColor;\n"
957 "uniform float FogRangeRecip;\n"
958 "uniform float FogPlaneViewDist;\n"
959 "uniform float FogHeightFade;\n"
960 "float FogVertex(void)\n"
962 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
963 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
965 "#ifdef USEFOGOUTSIDE\n"
966 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
968 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
970 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
974 "#ifdef USEOFFSETMAPPING\n"
975 "uniform float OffsetMapping_Scale;\n"
976 "vec2 OffsetMapping(vec2 TexCoord)\n"
978 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
979 " // 14 sample relief mapping: linear search and then binary search\n"
980 " // this basically steps forward a small amount repeatedly until it finds\n"
981 " // itself inside solid, then jitters forward and back using decreasing\n"
982 " // amounts to find the impact\n"
983 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
984 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
986 " vec3 RT = vec3(TexCoord, 1);\n"
987 " OffsetVector *= 0.1;\n"
988 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
994 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
997 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
998 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
999 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1000 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1001 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1004 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1005 " // this basically moves forward the full distance, and then backs up based\n"
1006 " // on height of samples\n"
1007 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1008 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1010 " TexCoord += OffsetVector;\n"
1011 " OffsetVector *= 0.333;\n"
1012 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1015 " return TexCoord;\n"
1018 "#endif // USEOFFSETMAPPING\n"
1020 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1021 "uniform sampler2D Texture_Attenuation;\n"
1022 "uniform samplerCube Texture_Cube;\n"
1025 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1027 "#ifdef USESHADOWMAPRECT\n"
1028 "# ifdef USESHADOWSAMPLER\n"
1029 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1031 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1035 "#ifdef USESHADOWMAP2D\n"
1036 "# ifdef USESHADOWSAMPLER\n"
1037 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1039 "uniform sampler2D Texture_ShadowMap2D;\n"
1043 "#ifdef USESHADOWMAPVSDCT\n"
1044 "uniform samplerCube Texture_CubeProjection;\n"
1047 "#ifdef USESHADOWMAPCUBE\n"
1048 "# ifdef USESHADOWSAMPLER\n"
1049 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1051 "uniform samplerCube Texture_ShadowMapCube;\n"
1055 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1056 "uniform vec2 ShadowMap_TextureScale;\n"
1057 "uniform vec4 ShadowMap_Parameters;\n"
1060 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1061 "# ifdef USESHADOWMAPORTHO\n"
1062 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1064 "# ifdef USESHADOWMAPVSDCT\n"
1065 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1067 " vec3 adir = abs(dir);\n"
1068 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1069 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1070 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1073 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1075 " vec3 adir = abs(dir);\n"
1076 " float ma = adir.z;\n"
1077 " vec4 proj = vec4(dir, 2.5);\n"
1078 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1079 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1080 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1081 " 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"
1085 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1087 "#ifdef USESHADOWMAPCUBE\n"
1088 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1090 " vec3 adir = abs(dir);\n"
1091 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1095 "# ifdef USESHADOWMAPRECT\n"
1096 "float ShadowMapCompare(vec3 dir)\n"
1098 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1100 "# ifdef USESHADOWSAMPLER\n"
1102 "# ifdef USESHADOWMAPPCF\n"
1103 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1104 " 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"
1106 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1111 "# ifdef USESHADOWMAPPCF\n"
1112 "# if USESHADOWMAPPCF > 1\n"
1113 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1114 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1115 " 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"
1116 " 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"
1117 " 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"
1118 " 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"
1119 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1120 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1122 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1123 " vec2 offset = fract(shadowmaptc.xy);\n"
1124 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1125 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1126 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1127 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1128 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1131 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1135 "# ifdef USESHADOWMAPORTHO\n"
1136 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1143 "# ifdef USESHADOWMAP2D\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1146 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1149 "# ifdef USESHADOWSAMPLER\n"
1150 "# ifdef USESHADOWMAPPCF\n"
1151 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1152 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1153 " 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"
1155 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1158 "# ifdef USESHADOWMAPPCF\n"
1159 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1160 "# ifdef GL_ARB_texture_gather\n"
1161 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1163 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1165 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1166 " center *= ShadowMap_TextureScale;\n"
1167 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1168 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1169 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1170 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1171 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1172 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1173 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1175 "# ifdef GL_EXT_gpu_shader4\n"
1176 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1178 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1180 "# if USESHADOWMAPPCF > 1\n"
1181 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1182 " center *= ShadowMap_TextureScale;\n"
1183 " 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"
1184 " 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"
1185 " 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"
1186 " 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"
1187 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1188 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1190 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1191 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1192 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1193 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1194 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1195 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1199 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1202 "# ifdef USESHADOWMAPORTHO\n"
1203 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1210 "# ifdef USESHADOWMAPCUBE\n"
1211 "float ShadowMapCompare(vec3 dir)\n"
1213 " // apply depth texture cubemap as light filter\n"
1214 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "# ifdef USESHADOWSAMPLER\n"
1217 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1224 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1225 "#endif // FRAGMENT_SHADER\n"
1230 "#ifdef MODE_DEFERREDGEOMETRY\n"
1231 "#ifdef VERTEX_SHADER\n"
1232 "uniform mat4 TexMatrix;\n"
1233 "#ifdef USEVERTEXTEXTUREBLEND\n"
1234 "uniform mat4 BackgroundTexMatrix;\n"
1236 "uniform mat4 ModelViewMatrix;\n"
1239 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1240 "#ifdef USEVERTEXTEXTUREBLEND\n"
1241 " gl_FrontColor = gl_Color;\n"
1242 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1245 " // transform unnormalized eye direction into tangent space\n"
1246 "#ifdef USEOFFSETMAPPING\n"
1247 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1248 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1249 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1250 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1253 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1254 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1255 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1256 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "#endif // VERTEX_SHADER\n"
1260 "#ifdef FRAGMENT_SHADER\n"
1263 "#ifdef USEOFFSETMAPPING\n"
1264 " // apply offsetmapping\n"
1265 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1266 "#define TexCoord TexCoordOffset\n"
1269 "#ifdef USEALPHAKILL\n"
1270 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1274 "#ifdef USEVERTEXTEXTUREBLEND\n"
1275 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1276 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1277 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1278 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1281 "#ifdef USEVERTEXTEXTUREBLEND\n"
1282 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1283 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1285 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1289 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1291 "#endif // FRAGMENT_SHADER\n"
1292 "#else // !MODE_DEFERREDGEOMETRY\n"
1297 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1298 "#ifdef VERTEX_SHADER\n"
1299 "uniform mat4 ModelViewMatrix;\n"
1302 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1303 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1305 "#endif // VERTEX_SHADER\n"
1307 "#ifdef FRAGMENT_SHADER\n"
1308 "uniform mat4 ViewToLight;\n"
1309 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1310 "uniform vec2 ScreenToDepth;\n"
1311 "uniform myhalf3 DeferredColor_Ambient;\n"
1312 "uniform myhalf3 DeferredColor_Diffuse;\n"
1313 "#ifdef USESPECULAR\n"
1314 "uniform myhalf3 DeferredColor_Specular;\n"
1315 "uniform myhalf SpecularPower;\n"
1317 "uniform myhalf2 PixelToScreenTexCoord;\n"
1320 " // calculate viewspace pixel position\n"
1321 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1323 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1324 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1325 " // decode viewspace pixel normal\n"
1326 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1327 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1328 " // surfacenormal = pixel normal in viewspace\n"
1329 " // LightVector = pixel to light in viewspace\n"
1330 " // CubeVector = position in lightspace\n"
1331 " // eyevector = pixel to view in viewspace\n"
1332 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1333 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1334 "#ifdef USEDIFFUSE\n"
1335 " // calculate diffuse shading\n"
1336 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1337 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1339 "#ifdef USESPECULAR\n"
1340 " // calculate directional shading\n"
1341 " vec3 eyevector = position * -1.0;\n"
1342 "# ifdef USEEXACTSPECULARMATH\n"
1343 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1345 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1346 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1350 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1351 " fade *= ShadowMapCompare(CubeVector);\n"
1354 "#ifdef USEDIFFUSE\n"
1355 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1357 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1359 "#ifdef USESPECULAR\n"
1360 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1362 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1365 "# ifdef USECUBEFILTER\n"
1366 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1367 " gl_FragData[0].rgb *= cubecolor;\n"
1368 " gl_FragData[1].rgb *= cubecolor;\n"
1371 "#endif // FRAGMENT_SHADER\n"
1372 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1377 "#ifdef VERTEX_SHADER\n"
1378 "uniform mat4 TexMatrix;\n"
1379 "#ifdef USEVERTEXTEXTUREBLEND\n"
1380 "uniform mat4 BackgroundTexMatrix;\n"
1382 "#ifdef MODE_LIGHTSOURCE\n"
1383 "uniform mat4 ModelToLight;\n"
1385 "#ifdef USESHADOWMAPORTHO\n"
1386 "uniform mat4 ShadowMapMatrix;\n"
1390 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1391 " gl_FrontColor = gl_Color;\n"
1393 " // copy the surface texcoord\n"
1394 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1395 "#ifdef USEVERTEXTEXTUREBLEND\n"
1396 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1398 "#ifdef USELIGHTMAP\n"
1399 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1402 "#ifdef MODE_LIGHTSOURCE\n"
1403 " // transform vertex position into light attenuation/cubemap space\n"
1404 " // (-1 to +1 across the light box)\n"
1405 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1407 "# ifdef USEDIFFUSE\n"
1408 " // transform unnormalized light direction into tangent space\n"
1409 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1410 " // normalize it per pixel)\n"
1411 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1412 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1413 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1414 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1418 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1419 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1420 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1421 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1424 " // transform unnormalized eye direction into tangent space\n"
1425 "#ifdef USEEYEVECTOR\n"
1426 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1427 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1428 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1429 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1433 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1434 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1437 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1438 " VectorS = gl_MultiTexCoord1.xyz;\n"
1439 " VectorT = gl_MultiTexCoord2.xyz;\n"
1440 " VectorR = gl_MultiTexCoord3.xyz;\n"
1443 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1444 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1446 "#ifdef USESHADOWMAPORTHO\n"
1447 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1450 "#ifdef USEREFLECTION\n"
1451 " ModelViewProjectionPosition = gl_Position;\n"
1454 "#endif // VERTEX_SHADER\n"
1459 "#ifdef FRAGMENT_SHADER\n"
1460 "#ifdef USEDEFERREDLIGHTMAP\n"
1461 "uniform myhalf2 PixelToScreenTexCoord;\n"
1462 "uniform myhalf3 DeferredMod_Diffuse;\n"
1463 "uniform myhalf3 DeferredMod_Specular;\n"
1465 "uniform myhalf3 Color_Ambient;\n"
1466 "uniform myhalf3 Color_Diffuse;\n"
1467 "uniform myhalf3 Color_Specular;\n"
1468 "uniform myhalf SpecularPower;\n"
1470 "uniform myhalf3 Color_Glow;\n"
1472 "uniform myhalf Alpha;\n"
1473 "#ifdef USEREFLECTION\n"
1474 "uniform vec4 DistortScaleRefractReflect;\n"
1475 "uniform vec4 ScreenScaleRefractReflect;\n"
1476 "uniform vec4 ScreenCenterRefractReflect;\n"
1477 "uniform myhalf4 ReflectColor;\n"
1479 "#ifdef USEREFLECTCUBE\n"
1480 "uniform mat4 ModelToReflectCube;\n"
1481 "uniform sampler2D Texture_ReflectMask;\n"
1482 "uniform samplerCube Texture_ReflectCube;\n"
1484 "#ifdef MODE_LIGHTDIRECTION\n"
1485 "uniform myhalf3 LightColor;\n"
1487 "#ifdef MODE_LIGHTSOURCE\n"
1488 "uniform myhalf3 LightColor;\n"
1492 "#ifdef USEOFFSETMAPPING\n"
1493 " // apply offsetmapping\n"
1494 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1495 "#define TexCoord TexCoordOffset\n"
1498 " // combine the diffuse textures (base, pants, shirt)\n"
1499 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1500 "#ifdef USEALPHAKILL\n"
1501 " if (color.a < 0.5)\n"
1504 " color.a *= Alpha;\n"
1505 "#ifdef USECOLORMAPPING\n"
1506 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1508 "#ifdef USEVERTEXTEXTUREBLEND\n"
1509 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1510 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1511 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1512 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1514 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1517 " // get the surface normal\n"
1518 "#ifdef USEVERTEXTEXTUREBLEND\n"
1519 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1521 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1524 " // get the material colors\n"
1525 " myhalf3 diffusetex = color.rgb;\n"
1526 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1527 "# ifdef USEVERTEXTEXTUREBLEND\n"
1528 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1530 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1534 "#ifdef USEREFLECTCUBE\n"
1535 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1536 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1537 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1538 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1544 "#ifdef MODE_LIGHTSOURCE\n"
1545 " // light source\n"
1546 "#ifdef USEDIFFUSE\n"
1547 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1548 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1549 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1550 "#ifdef USESPECULAR\n"
1551 "#ifdef USEEXACTSPECULARMATH\n"
1552 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1554 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1555 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1557 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1560 " color.rgb = diffusetex * Color_Ambient;\n"
1562 " color.rgb *= LightColor;\n"
1563 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1564 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1565 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1567 "# ifdef USECUBEFILTER\n"
1568 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1570 "#endif // MODE_LIGHTSOURCE\n"
1575 "#ifdef MODE_LIGHTDIRECTION\n"
1577 "#ifdef USEDIFFUSE\n"
1578 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1580 "#define lightcolor LightColor\n"
1581 "#endif // MODE_LIGHTDIRECTION\n"
1582 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1584 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1585 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1586 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1587 " // convert modelspace light vector to tangentspace\n"
1588 " myhalf3 lightnormal;\n"
1589 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1590 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1591 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1592 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1593 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1594 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1595 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1596 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1597 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1598 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1599 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1600 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1601 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1602 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1603 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1605 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1606 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1607 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1613 "#ifdef MODE_LIGHTMAP\n"
1614 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1615 "#endif // MODE_LIGHTMAP\n"
1616 "#ifdef MODE_VERTEXCOLOR\n"
1617 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1618 "#endif // MODE_VERTEXCOLOR\n"
1619 "#ifdef MODE_FLATCOLOR\n"
1620 " color.rgb = diffusetex * Color_Ambient;\n"
1621 "#endif // MODE_FLATCOLOR\n"
1627 "# ifdef USEDIFFUSE\n"
1628 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1629 "# ifdef USESPECULAR\n"
1630 "# ifdef USEEXACTSPECULARMATH\n"
1631 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1633 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1634 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1636 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1638 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1641 " color.rgb = diffusetex * Color_Ambient;\n"
1645 "#ifdef USESHADOWMAPORTHO\n"
1646 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1649 "#ifdef USEDEFERREDLIGHTMAP\n"
1650 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1651 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1652 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1656 "#ifdef USEVERTEXTEXTUREBLEND\n"
1657 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1659 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1664 "#ifdef MODE_LIGHTSOURCE\n"
1665 " color.rgb *= myhalf(FogVertex());\n"
1667 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1671 " // 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"
1672 "#ifdef USEREFLECTION\n"
1673 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1674 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1675 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1676 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1677 " // FIXME temporary hack to detect the case that the reflection\n"
1678 " // gets blackened at edges due to leaving the area that contains actual\n"
1680 " // Remove this 'ack once we have a better way to stop this thing from\n"
1682 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1683 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1684 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1685 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1686 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1687 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1690 " gl_FragColor = vec4(color);\n"
1692 "#endif // FRAGMENT_SHADER\n"
1694 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1695 "#endif // !MODE_DEFERREDGEOMETRY\n"
1696 "#endif // !MODE_WATER\n"
1697 "#endif // !MODE_REFRACTION\n"
1698 "#endif // !MODE_BLOOMBLUR\n"
1699 "#endif // !MODE_GENERIC\n"
1700 "#endif // !MODE_POSTPROCESS\n"
1701 "#endif // !MODE_SHOWDEPTH\n"
1702 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1706 =========================================================================================================================================================
1710 =========================================================================================================================================================
1714 =========================================================================================================================================================
1718 =========================================================================================================================================================
1722 =========================================================================================================================================================
1726 =========================================================================================================================================================
1730 =========================================================================================================================================================
1733 const char *builtincgshaderstring =
1734 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1735 "// written by Forest 'LordHavoc' Hale\n"
1736 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1738 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1741 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1742 "#define USELIGHTMAP\n"
1744 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1745 "#define USEEYEVECTOR\n"
1748 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1749 "#ifdef VERTEX_SHADER\n"
1752 "float4 gl_Vertex : POSITION,\n"
1753 "uniform float4x4 ModelViewProjectionMatrix,\n"
1754 "out float4 gl_Position : POSITION\n"
1757 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1760 "#else // !MODE_DEPTH_ORSHADOW\n"
1765 "#ifdef MODE_SHOWDEPTH\n"
1766 "#ifdef VERTEX_SHADER\n"
1769 "float4 gl_Vertex : POSITION,\n"
1770 "uniform float4x4 ModelViewProjectionMatrix,\n"
1771 "out float4 gl_Position : POSITION,\n"
1772 "out float4 gl_FrontColor : COLOR0\n"
1775 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1776 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1780 "#ifdef FRAGMENT_SHADER\n"
1783 "float4 gl_FrontColor : COLOR0,\n"
1784 "out float4 gl_FragColor : COLOR\n"
1787 " gl_FragColor = gl_FrontColor;\n"
1790 "#else // !MODE_SHOWDEPTH\n"
1795 "#ifdef MODE_POSTPROCESS\n"
1797 "#ifdef VERTEX_SHADER\n"
1800 "float4 gl_Vertex : POSITION,\n"
1801 "uniform float4x4 ModelViewProjectionMatrix,\n"
1802 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1803 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1804 "out float4 gl_Position : POSITION,\n"
1805 "out float2 TexCoord1 : TEXCOORD0,\n"
1806 "out float2 TexCoord2 : TEXCOORD1\n"
1809 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1810 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1812 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1817 "#ifdef FRAGMENT_SHADER\n"
1820 "float2 TexCoord1 : TEXCOORD0,\n"
1821 "float2 TexCoord2 : TEXCOORD1,\n"
1822 "uniform sampler2D Texture_First,\n"
1824 "uniform sampler2D Texture_Second,\n"
1826 "#ifdef USEGAMMARAMPS\n"
1827 "uniform sampler2D Texture_GammaRamps,\n"
1829 "#ifdef USESATURATION\n"
1830 "uniform float Saturation,\n"
1832 "#ifdef USEVIEWTINT\n"
1833 "uniform float4 ViewTintColor,\n"
1835 "uniform float4 UserVec1,\n"
1836 "uniform float4 UserVec2,\n"
1837 "uniform float4 UserVec3,\n"
1838 "uniform float4 UserVec4,\n"
1839 "uniform float ClientTime,\n"
1840 "uniform float2 PixelSize,\n"
1841 "out float4 gl_FragColor : COLOR\n"
1844 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1846 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1848 "#ifdef USEVIEWTINT\n"
1849 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1852 "#ifdef USEPOSTPROCESSING\n"
1853 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1854 "// 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"
1855 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1856 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1857 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1858 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1859 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1860 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1863 "#ifdef USESATURATION\n"
1864 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1865 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1866 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1867 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1870 "#ifdef USEGAMMARAMPS\n"
1871 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1872 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1873 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1877 "#else // !MODE_POSTPROCESS\n"
1882 "#ifdef MODE_GENERIC\n"
1883 "#ifdef VERTEX_SHADER\n"
1886 "float4 gl_Vertex : POSITION,\n"
1887 "uniform float4x4 ModelViewProjectionMatrix,\n"
1888 "float4 gl_Color : COLOR0,\n"
1889 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1890 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1891 "out float4 gl_Position : POSITION,\n"
1892 "out float4 gl_FrontColor : COLOR,\n"
1893 "out float2 TexCoord1 : TEXCOORD0,\n"
1894 "out float2 TexCoord2 : TEXCOORD1\n"
1897 " gl_FrontColor = gl_Color;\n"
1898 "#ifdef USEDIFFUSE\n"
1899 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1901 "#ifdef USESPECULAR\n"
1902 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1904 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1912 "float4 gl_FrontColor : COLOR,\n"
1913 "float2 TexCoord1 : TEXCOORD0,\n"
1914 "float2 TexCoord2 : TEXCOORD1,\n"
1915 "#ifdef USEDIFFUSE\n"
1916 "uniform sampler2D Texture_First,\n"
1918 "#ifdef USESPECULAR\n"
1919 "uniform sampler2D Texture_Second,\n"
1921 "out float4 gl_FragColor : COLOR\n"
1924 " gl_FragColor = gl_FrontColor;\n"
1925 "#ifdef USEDIFFUSE\n"
1926 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1929 "#ifdef USESPECULAR\n"
1930 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1931 "# ifdef USECOLORMAPPING\n"
1932 " gl_FragColor *= tex2;\n"
1935 " gl_FragColor += tex2;\n"
1937 "# ifdef USEVERTEXTEXTUREBLEND\n"
1938 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1943 "#else // !MODE_GENERIC\n"
1948 "#ifdef MODE_BLOOMBLUR\n"
1949 "#ifdef VERTEX_SHADER\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix,\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "out float4 gl_Position : POSITION,\n"
1956 "out float2 TexCoord : TEXCOORD0\n"
1959 " TexCoord = gl_MultiTexCoord0.xy;\n"
1960 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1964 "#ifdef FRAGMENT_SHADER\n"
1968 "float2 TexCoord : TEXCOORD0,\n"
1969 "uniform sampler2D Texture_First,\n"
1970 "uniform float4 BloomBlur_Parameters,\n"
1971 "out float4 gl_FragColor : COLOR\n"
1975 " float2 tc = TexCoord;\n"
1976 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1977 " tc += BloomBlur_Parameters.xy;\n"
1978 " for (i = 1;i < SAMPLES;i++)\n"
1980 " color += tex2D(Texture_First, tc).rgb;\n"
1981 " tc += BloomBlur_Parameters.xy;\n"
1983 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1986 "#else // !MODE_BLOOMBLUR\n"
1987 "#ifdef MODE_REFRACTION\n"
1988 "#ifdef VERTEX_SHADER\n"
1991 "float4 gl_Vertex : POSITION,\n"
1992 "uniform float4x4 ModelViewProjectionMatrix,\n"
1993 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1994 "uniform float4x4 TexMatrix,\n"
1995 "uniform float3 EyePosition,\n"
1996 "out float4 gl_Position : POSITION,\n"
1997 "out float2 TexCoord : TEXCOORD0,\n"
1998 "out float3 EyeVector : TEXCOORD1,\n"
1999 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2002 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2003 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2004 " ModelViewProjectionPosition = gl_Position;\n"
2008 "#ifdef FRAGMENT_SHADER\n"
2011 "float2 TexCoord : TEXCOORD0,\n"
2012 "float3 EyeVector : TEXCOORD1,\n"
2013 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2014 "uniform sampler2D Texture_Normal,\n"
2015 "uniform sampler2D Texture_Refraction,\n"
2016 "uniform sampler2D Texture_Reflection,\n"
2017 "uniform float4 DistortScaleRefractReflect,\n"
2018 "uniform float4 ScreenScaleRefractReflect,\n"
2019 "uniform float4 ScreenCenterRefractReflect,\n"
2020 "uniform float4 RefractColor,\n"
2021 "out float4 gl_FragColor : COLOR\n"
2024 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2025 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2026 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2027 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2028 " // FIXME temporary hack to detect the case that the reflection\n"
2029 " // gets blackened at edges due to leaving the area that contains actual\n"
2031 " // Remove this 'ack once we have a better way to stop this thing from\n"
2033 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2034 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2035 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2036 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2037 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2038 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2041 "#else // !MODE_REFRACTION\n"
2046 "#ifdef MODE_WATER\n"
2047 "#ifdef VERTEX_SHADER\n"
2051 "float4 gl_Vertex : POSITION,\n"
2052 "uniform float4x4 ModelViewProjectionMatrix,\n"
2053 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2054 "uniform float4x4 TexMatrix,\n"
2055 "uniform float3 EyePosition,\n"
2056 "out float4 gl_Position : POSITION,\n"
2057 "out float2 TexCoord : TEXCOORD0,\n"
2058 "out float3 EyeVector : TEXCOORD1,\n"
2059 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2062 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2063 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2064 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2065 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2066 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2067 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2068 " ModelViewProjectionPosition = gl_Position;\n"
2072 "#ifdef FRAGMENT_SHADER\n"
2075 "float2 TexCoord : TEXCOORD0,\n"
2076 "float3 EyeVector : TEXCOORD1,\n"
2077 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2078 "uniform sampler2D Texture_Normal,\n"
2079 "uniform sampler2D Texture_Refraction,\n"
2080 "uniform sampler2D Texture_Reflection,\n"
2081 "uniform float4 DistortScaleRefractReflect,\n"
2082 "uniform float4 ScreenScaleRefractReflect,\n"
2083 "uniform float4 ScreenCenterRefractReflect,\n"
2084 "uniform float4 RefractColor,\n"
2085 "uniform float4 ReflectColor,\n"
2086 "uniform float ReflectFactor,\n"
2087 "uniform float ReflectOffset,\n"
2088 "out float4 gl_FragColor : COLOR\n"
2091 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2092 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2093 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2094 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2095 " // FIXME temporary hack to detect the case that the reflection\n"
2096 " // gets blackened at edges due to leaving the area that contains actual\n"
2098 " // Remove this 'ack once we have a better way to stop this thing from\n"
2100 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2101 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2102 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2103 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2104 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2105 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2106 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2107 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2108 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2109 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2110 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2111 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2114 "#else // !MODE_WATER\n"
2119 "// 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"
2121 "// fragment shader specific:\n"
2122 "#ifdef FRAGMENT_SHADER\n"
2125 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2128 "#ifdef USEFOGOUTSIDE\n"
2129 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2131 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2133 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2137 "#ifdef USEOFFSETMAPPING\n"
2138 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2140 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2141 " // 14 sample relief mapping: linear search and then binary search\n"
2142 " // this basically steps forward a small amount repeatedly until it finds\n"
2143 " // itself inside solid, then jitters forward and back using decreasing\n"
2144 " // amounts to find the impact\n"
2145 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2146 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2147 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2148 " float3 RT = float3(TexCoord, 1);\n"
2149 " OffsetVector *= 0.1;\n"
2150 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2151 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2152 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2153 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2154 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2155 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2156 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2157 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2158 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2159 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2160 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2161 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2162 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2163 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2166 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2167 " // this basically moves forward the full distance, and then backs up based\n"
2168 " // on height of samples\n"
2169 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2170 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2171 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2172 " TexCoord += OffsetVector;\n"
2173 " OffsetVector *= 0.333;\n"
2174 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2175 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2176 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2177 " return TexCoord;\n"
2180 "#endif // USEOFFSETMAPPING\n"
2182 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2184 "# ifdef USESHADOWMAPORTHO\n"
2185 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2187 "# ifdef USESHADOWMAPVSDCT\n"
2188 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2190 " float3 adir = abs(dir);\n"
2191 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2192 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2193 " return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2196 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2198 " float3 adir = abs(dir);\n"
2199 " float ma = adir.z;\n"
2200 " float4 proj = float4(dir, 2.5);\n"
2201 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2202 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2203 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2204 " 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"
2208 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2210 "#ifdef USESHADOWMAPCUBE\n"
2211 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2213 " float3 adir = abs(dir);\n"
2214 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2218 "# ifdef USESHADOWMAPRECT\n"
2219 "#ifdef USESHADOWMAPVSDCT\n"
2220 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2222 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2225 "#ifdef USESHADOWMAPVSDCT\n"
2226 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2228 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2231 "# ifdef USESHADOWSAMPLER\n"
2233 "# ifdef USESHADOWMAPPCF\n"
2234 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2235 " 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"
2237 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2242 "# ifdef USESHADOWMAPPCF\n"
2243 "# if USESHADOWMAPPCF > 1\n"
2244 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2245 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2246 " 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"
2247 " 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"
2248 " 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"
2249 " 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"
2250 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2251 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2253 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2254 " float2 offset = frac(shadowmaptc.xy);\n"
2255 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2256 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2257 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2258 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2259 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2262 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2266 "# ifdef USESHADOWMAPORTHO\n"
2267 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2274 "# ifdef USESHADOWMAP2D\n"
2275 "#ifdef USESHADOWMAPVSDCT\n"
2276 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2278 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2281 "#ifdef USESHADOWMAPVSDCT\n"
2282 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2284 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2288 "# ifdef USESHADOWSAMPLER\n"
2289 "# ifdef USESHADOWMAPPCF\n"
2290 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2291 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2292 " 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"
2294 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2297 "# ifdef USESHADOWMAPPCF\n"
2298 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2299 "# ifdef GL_ARB_texture_gather\n"
2300 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2302 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2304 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2305 " center *= ShadowMap_TextureScale;\n"
2306 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2307 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2308 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2309 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2310 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2311 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2312 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2314 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2315 "# if USESHADOWMAPPCF > 1\n"
2316 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2317 " center *= ShadowMap_TextureScale;\n"
2318 " 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"
2319 " 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"
2320 " 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"
2321 " 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"
2322 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2323 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2325 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2326 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2327 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2328 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2329 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2330 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2334 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2337 "# ifdef USESHADOWMAPORTHO\n"
2338 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2345 "# ifdef USESHADOWMAPCUBE\n"
2346 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2348 " // apply depth texture cubemap as light filter\n"
2349 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2351 "# ifdef USESHADOWSAMPLER\n"
2352 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2354 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2359 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2360 "#endif // FRAGMENT_SHADER\n"
2365 "#ifdef MODE_DEFERREDGEOMETRY\n"
2366 "#ifdef VERTEX_SHADER\n"
2369 "float4 gl_Vertex : POSITION,\n"
2370 "uniform float4x4 ModelViewProjectionMatrix,\n"
2371 "#ifdef USEVERTEXTEXTUREBLEND\n"
2372 "float4 gl_Color : COLOR0,\n"
2374 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2375 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2376 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2377 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2378 "uniform float4x4 TexMatrix,\n"
2379 "#ifdef USEVERTEXTEXTUREBLEND\n"
2380 "uniform float4x4 BackgroundTexMatrix,\n"
2382 "uniform float4x4 ModelViewMatrix,\n"
2383 "#ifdef USEOFFSETMAPPING\n"
2384 "uniform float3 EyePosition,\n"
2386 "out float4 gl_Position : POSITION,\n"
2387 "out float4 gl_FrontColor : COLOR,\n"
2388 "out float4 TexCoordBoth : TEXCOORD0,\n"
2389 "#ifdef USEOFFSETMAPPING\n"
2390 "out float3 EyeVector : TEXCOORD2,\n"
2392 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2393 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2394 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2397 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2398 "#ifdef USEVERTEXTEXTUREBLEND\n"
2399 " gl_FrontColor = gl_Color;\n"
2400 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2403 " // transform unnormalized eye direction into tangent space\n"
2404 "#ifdef USEOFFSETMAPPING\n"
2405 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2406 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2407 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2408 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2411 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2412 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2413 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2414 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2416 "#endif // VERTEX_SHADER\n"
2418 "#ifdef FRAGMENT_SHADER\n"
2421 "float4 TexCoordBoth : TEXCOORD0,\n"
2422 "float3 EyeVector : TEXCOORD2,\n"
2423 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2424 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2425 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2426 "uniform sampler2D Texture_Normal,\n"
2427 "#ifdef USEALPHAKILL\n"
2428 "uniform sampler2D Texture_Color,\n"
2430 "uniform sampler2D Texture_Gloss,\n"
2431 "#ifdef USEVERTEXTEXTUREBLEND\n"
2432 "uniform sampler2D Texture_SecondaryNormal,\n"
2433 "uniform sampler2D Texture_SecondaryGloss,\n"
2435 "#ifdef USEOFFSETMAPPING\n"
2436 "uniform float OffsetMapping_Scale,\n"
2438 "uniform half SpecularPower,\n"
2439 "out float4 gl_FragColor : COLOR\n"
2442 " float2 TexCoord = TexCoordBoth.xy;\n"
2443 "#ifdef USEOFFSETMAPPING\n"
2444 " // apply offsetmapping\n"
2445 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2446 "#define TexCoord TexCoordOffset\n"
2449 "#ifdef USEALPHAKILL\n"
2450 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2454 "#ifdef USEVERTEXTEXTUREBLEND\n"
2455 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2456 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2457 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2458 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2461 "#ifdef USEVERTEXTEXTUREBLEND\n"
2462 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2463 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2465 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2466 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2469 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2471 "#endif // FRAGMENT_SHADER\n"
2472 "#else // !MODE_DEFERREDGEOMETRY\n"
2477 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2478 "#ifdef VERTEX_SHADER\n"
2481 "float4 gl_Vertex : POSITION,\n"
2482 "uniform float4x4 ModelViewProjectionMatrix,\n"
2483 "uniform float4x4 ModelViewMatrix,\n"
2484 "out float4 gl_Position : POSITION,\n"
2485 "out float4 ModelViewPosition : TEXCOORD0\n"
2488 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2489 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2491 "#endif // VERTEX_SHADER\n"
2493 "#ifdef FRAGMENT_SHADER\n"
2496 "float2 Pixel : WPOS,\n"
2497 "float4 ModelViewPosition : TEXCOORD0,\n"
2498 "uniform float4x4 ViewToLight,\n"
2499 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2500 "uniform float3 LightPosition,\n"
2501 "uniform half2 PixelToScreenTexCoord,\n"
2502 "uniform half3 DeferredColor_Ambient,\n"
2503 "uniform half3 DeferredColor_Diffuse,\n"
2504 "#ifdef USESPECULAR\n"
2505 "uniform half3 DeferredColor_Specular,\n"
2506 "uniform half SpecularPower,\n"
2508 "uniform sampler2D Texture_Attenuation,\n"
2509 "uniform sampler2D Texture_ScreenDepth,\n"
2510 "uniform sampler2D Texture_ScreenNormalMap,\n"
2512 "#ifdef USESHADOWMAPRECT\n"
2513 "# ifdef USESHADOWSAMPLER\n"
2514 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2516 "uniform samplerRECT Texture_ShadowMapRect,\n"
2520 "#ifdef USESHADOWMAP2D\n"
2521 "# ifdef USESHADOWSAMPLER\n"
2522 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2524 "uniform sampler2D Texture_ShadowMap2D,\n"
2528 "#ifdef USESHADOWMAPVSDCT\n"
2529 "uniform samplerCUBE Texture_CubeProjection,\n"
2532 "#ifdef USESHADOWMAPCUBE\n"
2533 "# ifdef USESHADOWSAMPLER\n"
2534 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2536 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2540 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2541 "uniform float2 ShadowMap_TextureScale,\n"
2542 "uniform float4 ShadowMap_Parameters,\n"
2545 "out float4 gl_FragData0 : COLOR0,\n"
2546 "out float4 gl_FragData1 : COLOR1\n"
2549 " // calculate viewspace pixel position\n"
2550 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2551 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2552 " float3 position;\n"
2553 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2554 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2555 " // decode viewspace pixel normal\n"
2556 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2557 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2558 " // surfacenormal = pixel normal in viewspace\n"
2559 " // LightVector = pixel to light in viewspace\n"
2560 " // CubeVector = position in lightspace\n"
2561 " // eyevector = pixel to view in viewspace\n"
2562 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2563 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2564 "#ifdef USEDIFFUSE\n"
2565 " // calculate diffuse shading\n"
2566 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2567 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2569 "#ifdef USESPECULAR\n"
2570 " // calculate directional shading\n"
2571 " float3 eyevector = position * -1.0;\n"
2572 "# ifdef USEEXACTSPECULARMATH\n"
2573 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2575 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2576 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2580 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2581 " fade *= ShadowMapCompare(CubeVector,\n"
2582 "# if defined(USESHADOWMAP2D)\n"
2583 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2585 "# if defined(USESHADOWMAPRECT)\n"
2586 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2588 "# if defined(USESHADOWMAPCUBE)\n"
2589 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2592 "#ifdef USESHADOWMAPVSDCT\n"
2593 ", Texture_CubeProjection\n"
2598 "#ifdef USEDIFFUSE\n"
2599 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2601 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2603 "#ifdef USESPECULAR\n"
2604 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2606 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2609 "# ifdef USECUBEFILTER\n"
2610 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2611 " gl_FragData0.rgb *= cubecolor;\n"
2612 " gl_FragData1.rgb *= cubecolor;\n"
2615 "#endif // FRAGMENT_SHADER\n"
2616 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2621 "#ifdef VERTEX_SHADER\n"
2624 "float4 gl_Vertex : POSITION,\n"
2625 "uniform float4x4 ModelViewProjectionMatrix,\n"
2626 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2627 "float4 gl_Color : COLOR0,\n"
2629 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2630 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2631 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2632 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2633 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2635 "uniform float3 EyePosition,\n"
2636 "uniform float4x4 TexMatrix,\n"
2637 "#ifdef USEVERTEXTEXTUREBLEND\n"
2638 "uniform float4x4 BackgroundTexMatrix,\n"
2640 "#ifdef MODE_LIGHTSOURCE\n"
2641 "uniform float4x4 ModelToLight,\n"
2643 "#ifdef MODE_LIGHTSOURCE\n"
2644 "uniform float3 LightPosition,\n"
2646 "#ifdef MODE_LIGHTDIRECTION\n"
2647 "uniform float3 LightDir,\n"
2649 "uniform float4 FogPlane,\n"
2650 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2651 "uniform float3 LightPosition,\n"
2653 "#ifdef USESHADOWMAPORTHO\n"
2654 "uniform float4x4 ShadowMapMatrix,\n"
2657 "out float4 gl_FrontColor : COLOR,\n"
2658 "out float4 TexCoordBoth : TEXCOORD0,\n"
2659 "#ifdef USELIGHTMAP\n"
2660 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2662 "#ifdef USEEYEVECTOR\n"
2663 "out float3 EyeVector : TEXCOORD2,\n"
2665 "#ifdef USEREFLECTION\n"
2666 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2669 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2671 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2672 "out float3 LightVector : TEXCOORD1,\n"
2674 "#ifdef MODE_LIGHTSOURCE\n"
2675 "out float3 CubeVector : TEXCOORD3,\n"
2677 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2678 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2682 "#ifdef USESHADOWMAPORTHO\n"
2683 "out float3 ShadowMapTC : TEXCOORD8,\n"
2685 "out float4 gl_Position : POSITION\n"
2688 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2689 " gl_FrontColor = gl_Color;\n"
2691 " // copy the surface texcoord\n"
2692 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2693 "#ifdef USEVERTEXTEXTUREBLEND\n"
2694 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2696 "#ifdef USELIGHTMAP\n"
2697 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2700 "#ifdef MODE_LIGHTSOURCE\n"
2701 " // transform vertex position into light attenuation/cubemap space\n"
2702 " // (-1 to +1 across the light box)\n"
2703 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2705 "# ifdef USEDIFFUSE\n"
2706 " // transform unnormalized light direction into tangent space\n"
2707 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2708 " // normalize it per pixel)\n"
2709 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2710 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2711 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2712 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2716 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2717 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2718 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2719 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2722 " // transform unnormalized eye direction into tangent space\n"
2723 "#ifdef USEEYEVECTOR\n"
2724 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2725 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2726 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2727 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2731 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2732 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2735 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2736 " VectorS = gl_MultiTexCoord1.xyz;\n"
2737 " VectorT = gl_MultiTexCoord2.xyz;\n"
2738 " VectorR = gl_MultiTexCoord3.xyz;\n"
2741 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2742 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2744 "#ifdef USESHADOWMAPORTHO\n"
2745 " ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2748 "#ifdef USEREFLECTION\n"
2749 " ModelViewProjectionPosition = gl_Position;\n"
2752 "#endif // VERTEX_SHADER\n"
2757 "#ifdef FRAGMENT_SHADER\n"
2760 "#ifdef USEDEFERREDLIGHTMAP\n"
2761 "float2 Pixel : WPOS,\n"
2763 "float4 gl_FrontColor : COLOR,\n"
2764 "float4 TexCoordBoth : TEXCOORD0,\n"
2765 "#ifdef USELIGHTMAP\n"
2766 "float2 TexCoordLightmap : TEXCOORD1,\n"
2768 "#ifdef USEEYEVECTOR\n"
2769 "float3 EyeVector : TEXCOORD2,\n"
2771 "#ifdef USEREFLECTION\n"
2772 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2775 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2777 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2778 "float3 LightVector : TEXCOORD1,\n"
2780 "#ifdef MODE_LIGHTSOURCE\n"
2781 "float3 CubeVector : TEXCOORD3,\n"
2783 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2784 "float4 ModelViewPosition : TEXCOORD0,\n"
2786 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2787 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2788 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2789 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2791 "#ifdef USESHADOWMAPORTHO\n"
2792 "float3 ShadowMapTC : TEXCOORD8,\n"
2795 "uniform sampler2D Texture_Normal,\n"
2796 "uniform sampler2D Texture_Color,\n"
2797 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2798 "uniform sampler2D Texture_Gloss,\n"
2801 "uniform sampler2D Texture_Glow,\n"
2803 "#ifdef USEVERTEXTEXTUREBLEND\n"
2804 "uniform sampler2D Texture_SecondaryNormal,\n"
2805 "uniform sampler2D Texture_SecondaryColor,\n"
2806 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2807 "uniform sampler2D Texture_SecondaryGloss,\n"
2810 "uniform sampler2D Texture_SecondaryGlow,\n"
2813 "#ifdef USECOLORMAPPING\n"
2814 "uniform sampler2D Texture_Pants,\n"
2815 "uniform sampler2D Texture_Shirt,\n"
2818 "uniform sampler2D Texture_FogMask,\n"
2820 "#ifdef USELIGHTMAP\n"
2821 "uniform sampler2D Texture_Lightmap,\n"
2823 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2824 "uniform sampler2D Texture_Deluxemap,\n"
2826 "#ifdef USEREFLECTION\n"
2827 "uniform sampler2D Texture_Reflection,\n"
2830 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2831 "uniform sampler2D Texture_ScreenDepth,\n"
2832 "uniform sampler2D Texture_ScreenNormalMap,\n"
2834 "#ifdef USEDEFERREDLIGHTMAP\n"
2835 "uniform sampler2D Texture_ScreenDiffuse,\n"
2836 "uniform sampler2D Texture_ScreenSpecular,\n"
2839 "#ifdef USECOLORMAPPING\n"
2840 "uniform half3 Color_Pants,\n"
2841 "uniform half3 Color_Shirt,\n"
2844 "uniform float3 FogColor,\n"
2845 "uniform float FogRangeRecip,\n"
2846 "uniform float FogPlaneViewDist,\n"
2847 "uniform float FogHeightFade,\n"
2850 "#ifdef USEOFFSETMAPPING\n"
2851 "uniform float OffsetMapping_Scale,\n"
2854 "#ifdef USEDEFERREDLIGHTMAP\n"
2855 "uniform half2 PixelToScreenTexCoord,\n"
2856 "uniform half3 DeferredMod_Diffuse,\n"
2857 "uniform half3 DeferredMod_Specular,\n"
2859 "uniform half3 Color_Ambient,\n"
2860 "uniform half3 Color_Diffuse,\n"
2861 "uniform half3 Color_Specular,\n"
2862 "uniform half SpecularPower,\n"
2864 "uniform half3 Color_Glow,\n"
2866 "uniform half Alpha,\n"
2867 "#ifdef USEREFLECTION\n"
2868 "uniform float4 DistortScaleRefractReflect,\n"
2869 "uniform float4 ScreenScaleRefractReflect,\n"
2870 "uniform float4 ScreenCenterRefractReflect,\n"
2871 "uniform half4 ReflectColor,\n"
2873 "#ifdef USEREFLECTCUBE\n"
2874 "uniform float4x4 ModelToReflectCube,\n"
2875 "uniform sampler2D Texture_ReflectMask,\n"
2876 "uniform samplerCUBE Texture_ReflectCube,\n"
2878 "#ifdef MODE_LIGHTDIRECTION\n"
2879 "uniform half3 LightColor,\n"
2881 "#ifdef MODE_LIGHTSOURCE\n"
2882 "uniform half3 LightColor,\n"
2885 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2886 "uniform sampler2D Texture_Attenuation,\n"
2887 "uniform samplerCUBE Texture_Cube,\n"
2890 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2892 "#ifdef USESHADOWMAPRECT\n"
2893 "# ifdef USESHADOWSAMPLER\n"
2894 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2896 "uniform samplerRECT Texture_ShadowMapRect,\n"
2900 "#ifdef USESHADOWMAP2D\n"
2901 "# ifdef USESHADOWSAMPLER\n"
2902 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2904 "uniform sampler2D Texture_ShadowMap2D,\n"
2908 "#ifdef USESHADOWMAPVSDCT\n"
2909 "uniform samplerCUBE Texture_CubeProjection,\n"
2912 "#ifdef USESHADOWMAPCUBE\n"
2913 "# ifdef USESHADOWSAMPLER\n"
2914 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2916 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2920 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2921 "uniform float2 ShadowMap_TextureScale,\n"
2922 "uniform float4 ShadowMap_Parameters,\n"
2924 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2926 "out float4 gl_FragColor : COLOR\n"
2929 " float2 TexCoord = TexCoordBoth.xy;\n"
2930 "#ifdef USEVERTEXTEXTUREBLEND\n"
2931 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2933 "#ifdef USEOFFSETMAPPING\n"
2934 " // apply offsetmapping\n"
2935 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2936 "#define TexCoord TexCoordOffset\n"
2939 " // combine the diffuse textures (base, pants, shirt)\n"
2940 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2941 "#ifdef USEALPHAKILL\n"
2942 " if (color.a < 0.5)\n"
2945 " color.a *= Alpha;\n"
2946 "#ifdef USECOLORMAPPING\n"
2947 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2949 "#ifdef USEVERTEXTEXTUREBLEND\n"
2950 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2951 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2952 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2953 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2955 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2958 " // get the surface normal\n"
2959 "#ifdef USEVERTEXTEXTUREBLEND\n"
2960 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2962 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2965 " // get the material colors\n"
2966 " half3 diffusetex = color.rgb;\n"
2967 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2968 "# ifdef USEVERTEXTEXTUREBLEND\n"
2969 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2971 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2975 "#ifdef USEREFLECTCUBE\n"
2976 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2977 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2978 " float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2979 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2985 "#ifdef MODE_LIGHTSOURCE\n"
2986 " // light source\n"
2987 "#ifdef USEDIFFUSE\n"
2988 " half3 lightnormal = half3(normalize(LightVector));\n"
2989 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2990 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2991 "#ifdef USESPECULAR\n"
2992 "#ifdef USEEXACTSPECULARMATH\n"
2993 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
2995 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2996 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
2998 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3001 " color.rgb = diffusetex * Color_Ambient;\n"
3003 " color.rgb *= LightColor;\n"
3004 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3005 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3006 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3007 "# if defined(USESHADOWMAP2D)\n"
3008 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3010 "# if defined(USESHADOWMAPRECT)\n"
3011 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3013 "# if defined(USESHADOWMAPCUBE)\n"
3014 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3017 "#ifdef USESHADOWMAPVSDCT\n"
3018 ", Texture_CubeProjection\n"
3023 "# ifdef USECUBEFILTER\n"
3024 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3026 "#endif // MODE_LIGHTSOURCE\n"
3031 "#ifdef MODE_LIGHTDIRECTION\n"
3033 "#ifdef USEDIFFUSE\n"
3034 " half3 lightnormal = half3(normalize(LightVector));\n"
3036 "#define lightcolor LightColor\n"
3037 "#endif // MODE_LIGHTDIRECTION\n"
3038 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3040 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3041 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3042 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3043 " // convert modelspace light vector to tangentspace\n"
3044 " half3 lightnormal;\n"
3045 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3046 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3047 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3048 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3049 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3050 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3051 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3052 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3053 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3054 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3055 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3056 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3057 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3058 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3059 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3061 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3062 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3063 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3069 "#ifdef MODE_LIGHTMAP\n"
3070 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3071 "#endif // MODE_LIGHTMAP\n"
3072 "#ifdef MODE_VERTEXCOLOR\n"
3073 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3074 "#endif // MODE_VERTEXCOLOR\n"
3075 "#ifdef MODE_FLATCOLOR\n"
3076 " color.rgb = diffusetex * Color_Ambient;\n"
3077 "#endif // MODE_FLATCOLOR\n"
3083 "# ifdef USEDIFFUSE\n"
3084 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3085 "# ifdef USESPECULAR\n"
3086 "# ifdef USEEXACTSPECULARMATH\n"
3087 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3089 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3090 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3092 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3094 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3097 " color.rgb = diffusetex * Color_Ambient;\n"
3101 "#ifdef USESHADOWMAPORTHO\n"
3102 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3103 "# if defined(USESHADOWMAP2D)\n"
3104 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3106 "# if defined(USESHADOWMAPRECT)\n"
3107 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3112 "#ifdef USEDEFERREDLIGHTMAP\n"
3113 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3114 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3115 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3119 "#ifdef USEVERTEXTEXTUREBLEND\n"
3120 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3122 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3130 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3134 " // 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"
3135 "#ifdef USEREFLECTION\n"
3136 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3137 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3138 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3139 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3140 " // FIXME temporary hack to detect the case that the reflection\n"
3141 " // gets blackened at edges due to leaving the area that contains actual\n"
3143 " // Remove this 'ack once we have a better way to stop this thing from\n"
3145 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3146 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3147 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3148 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3149 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3150 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3153 " gl_FragColor = float4(color);\n"
3155 "#endif // FRAGMENT_SHADER\n"
3157 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3158 "#endif // !MODE_DEFERREDGEOMETRY\n"
3159 "#endif // !MODE_WATER\n"
3160 "#endif // !MODE_REFRACTION\n"
3161 "#endif // !MODE_BLOOMBLUR\n"
3162 "#endif // !MODE_GENERIC\n"
3163 "#endif // !MODE_POSTPROCESS\n"
3164 "#endif // !MODE_SHOWDEPTH\n"
3165 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3168 char *glslshaderstring = NULL;
3169 char *cgshaderstring = NULL;
3171 //=======================================================================================================================================================
3173 typedef struct shaderpermutationinfo_s
3175 const char *pretext;
3178 shaderpermutationinfo_t;
3180 typedef struct shadermodeinfo_s
3182 const char *vertexfilename;
3183 const char *geometryfilename;
3184 const char *fragmentfilename;
3185 const char *pretext;
3190 typedef enum shaderpermutation_e
3192 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3193 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3194 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3195 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3196 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3197 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3198 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3199 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3200 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3201 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3202 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3203 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3204 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3205 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3206 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3207 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3208 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3209 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3210 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3211 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3212 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3213 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3214 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3215 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3216 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3217 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3218 SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3219 SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3220 SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3221 SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3223 shaderpermutation_t;
3225 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3226 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3228 {"#define USEDIFFUSE\n", " diffuse"},
3229 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3230 {"#define USEVIEWTINT\n", " viewtint"},
3231 {"#define USECOLORMAPPING\n", " colormapping"},
3232 {"#define USESATURATION\n", " saturation"},
3233 {"#define USEFOGINSIDE\n", " foginside"},
3234 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3235 {"#define USEGAMMARAMPS\n", " gammaramps"},
3236 {"#define USECUBEFILTER\n", " cubefilter"},
3237 {"#define USEGLOW\n", " glow"},
3238 {"#define USEBLOOM\n", " bloom"},
3239 {"#define USESPECULAR\n", " specular"},
3240 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3241 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3242 {"#define USEREFLECTION\n", " reflection"},
3243 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3244 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3245 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3246 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3247 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3248 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3249 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3250 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3251 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3252 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3253 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3254 {"#define USEALPHAKILL\n", " alphakill"},
3255 {"#define USEREFLECTCUBE\n", " reflectcube"},
3258 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3259 typedef enum shadermode_e
3261 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3262 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3263 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3264 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3265 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3266 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3267 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3268 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3269 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3270 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3271 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3272 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3273 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3274 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3275 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3280 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3281 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3283 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3284 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3285 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3286 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3287 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3288 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3289 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3290 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3291 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3292 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3293 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3294 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3295 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3296 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3297 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3301 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3303 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3304 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3305 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3306 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3307 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3308 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3309 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3310 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3311 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3312 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3313 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3314 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3315 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3316 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3317 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3321 struct r_glsl_permutation_s;
3322 typedef struct r_glsl_permutation_s
3324 /// hash lookup data
3325 struct r_glsl_permutation_s *hashnext;
3327 unsigned int permutation;
3329 /// indicates if we have tried compiling this permutation already
3331 /// 0 if compilation failed
3333 /// locations of detected uniforms in program object, or -1 if not found
3334 int loc_Texture_First;
3335 int loc_Texture_Second;
3336 int loc_Texture_GammaRamps;
3337 int loc_Texture_Normal;
3338 int loc_Texture_Color;
3339 int loc_Texture_Gloss;
3340 int loc_Texture_Glow;
3341 int loc_Texture_SecondaryNormal;
3342 int loc_Texture_SecondaryColor;
3343 int loc_Texture_SecondaryGloss;
3344 int loc_Texture_SecondaryGlow;
3345 int loc_Texture_Pants;
3346 int loc_Texture_Shirt;
3347 int loc_Texture_FogMask;
3348 int loc_Texture_Lightmap;
3349 int loc_Texture_Deluxemap;
3350 int loc_Texture_Attenuation;
3351 int loc_Texture_Cube;
3352 int loc_Texture_Refraction;
3353 int loc_Texture_Reflection;
3354 int loc_Texture_ShadowMapRect;
3355 int loc_Texture_ShadowMapCube;
3356 int loc_Texture_ShadowMap2D;
3357 int loc_Texture_CubeProjection;
3358 int loc_Texture_ScreenDepth;
3359 int loc_Texture_ScreenNormalMap;
3360 int loc_Texture_ScreenDiffuse;
3361 int loc_Texture_ScreenSpecular;
3362 int loc_Texture_ReflectMask;
3363 int loc_Texture_ReflectCube;
3365 int loc_BloomBlur_Parameters;
3367 int loc_Color_Ambient;
3368 int loc_Color_Diffuse;
3369 int loc_Color_Specular;
3371 int loc_Color_Pants;
3372 int loc_Color_Shirt;
3373 int loc_DeferredColor_Ambient;
3374 int loc_DeferredColor_Diffuse;
3375 int loc_DeferredColor_Specular;
3376 int loc_DeferredMod_Diffuse;
3377 int loc_DeferredMod_Specular;
3378 int loc_DistortScaleRefractReflect;
3379 int loc_EyePosition;
3381 int loc_FogHeightFade;
3383 int loc_FogPlaneViewDist;
3384 int loc_FogRangeRecip;
3387 int loc_LightPosition;
3388 int loc_OffsetMapping_Scale;
3390 int loc_ReflectColor;
3391 int loc_ReflectFactor;
3392 int loc_ReflectOffset;
3393 int loc_RefractColor;
3395 int loc_ScreenCenterRefractReflect;
3396 int loc_ScreenScaleRefractReflect;
3397 int loc_ScreenToDepth;
3398 int loc_ShadowMap_Parameters;
3399 int loc_ShadowMap_TextureScale;
3400 int loc_SpecularPower;
3405 int loc_ViewTintColor;
3406 int loc_ViewToLight;
3407 int loc_ModelToLight;
3409 int loc_BackgroundTexMatrix;
3410 int loc_ModelViewProjectionMatrix;
3411 int loc_ModelViewMatrix;
3412 int loc_PixelToScreenTexCoord;
3413 int loc_ModelToReflectCube;
3414 int loc_ShadowMapMatrix;
3416 r_glsl_permutation_t;
3418 #define SHADERPERMUTATION_HASHSIZE 256
3420 /// information about each possible shader permutation
3421 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3422 /// currently selected permutation
3423 r_glsl_permutation_t *r_glsl_permutation;
3424 /// storage for permutations linked in the hash table
3425 memexpandablearray_t r_glsl_permutationarray;
3427 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3429 //unsigned int hashdepth = 0;
3430 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3431 r_glsl_permutation_t *p;
3432 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3434 if (p->mode == mode && p->permutation == permutation)
3436 //if (hashdepth > 10)
3437 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3442 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3444 p->permutation = permutation;
3445 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3446 r_glsl_permutationhash[mode][hashindex] = p;
3447 //if (hashdepth > 10)
3448 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3452 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3455 if (!filename || !filename[0])
3457 if (!strcmp(filename, "glsl/default.glsl"))
3459 if (!glslshaderstring)
3461 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3462 if (glslshaderstring)
3463 Con_DPrintf("Loading shaders from file %s...\n", filename);
3465 glslshaderstring = (char *)builtinshaderstring;
3467 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3468 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3469 return shaderstring;
3471 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3474 if (printfromdisknotice)
3475 Con_DPrintf("from disk %s... ", filename);
3476 return shaderstring;
3478 return shaderstring;
3481 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3484 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3485 int vertstrings_count = 0;
3486 int geomstrings_count = 0;
3487 int fragstrings_count = 0;
3488 char *vertexstring, *geometrystring, *fragmentstring;
3489 const char *vertstrings_list[32+3];
3490 const char *geomstrings_list[32+3];
3491 const char *fragstrings_list[32+3];
3492 char permutationname[256];
3499 permutationname[0] = 0;
3500 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3501 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3502 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3504 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3506 // the first pretext is which type of shader to compile as
3507 // (later these will all be bound together as a program object)
3508 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3509 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3510 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3512 // the second pretext is the mode (for example a light source)
3513 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3514 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3515 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3516 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3518 // now add all the permutation pretexts
3519 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3521 if (permutation & (1<<i))
3523 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3524 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3525 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3526 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3530 // keep line numbers correct
3531 vertstrings_list[vertstrings_count++] = "\n";
3532 geomstrings_list[geomstrings_count++] = "\n";
3533 fragstrings_list[fragstrings_count++] = "\n";
3537 // now append the shader text itself
3538 vertstrings_list[vertstrings_count++] = vertexstring;
3539 geomstrings_list[geomstrings_count++] = geometrystring;
3540 fragstrings_list[fragstrings_count++] = fragmentstring;
3542 // if any sources were NULL, clear the respective list
3544 vertstrings_count = 0;
3545 if (!geometrystring)
3546 geomstrings_count = 0;
3547 if (!fragmentstring)
3548 fragstrings_count = 0;
3550 // compile the shader program
3551 if (vertstrings_count + geomstrings_count + fragstrings_count)
3552 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3556 qglUseProgramObjectARB(p->program);CHECKGLERROR
3557 // look up all the uniform variable names we care about, so we don't
3558 // have to look them up every time we set them
3560 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3561 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3562 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3563 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3564 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3565 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3566 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3567 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3568 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3569 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3570 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3571 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3572 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3573 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3574 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3575 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3576 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3577 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3578 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3579 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3580 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3581 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3582 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3583 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3584 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3585 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3586 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3587 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3588 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3589 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3590 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3591 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3592 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3593 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3594 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3595 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3596 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3597 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3598 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3599 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3600 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3601 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3602 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3603 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3604 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3605 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3606 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3607 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3608 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3609 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3610 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3611 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3612 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3613 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3614 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3615 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3616 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3617 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3618 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3619 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3620 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3621 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3622 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3623 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3624 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3625 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3626 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3627 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3628 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3629 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3630 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3631 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3632 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3633 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3634 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3635 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3636 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3637 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3638 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3639 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3640 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3641 // initialize the samplers to refer to the texture units we use
3642 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3643 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3644 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3645 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3646 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3647 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3648 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3649 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3650 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3651 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3652 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3653 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3654 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3655 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3656 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3657 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3658 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3659 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3660 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3661 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3662 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3663 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3664 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3665 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3666 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3667 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3668 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3669 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3670 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3671 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3673 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3676 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3680 Mem_Free(vertexstring);
3682 Mem_Free(geometrystring);
3684 Mem_Free(fragmentstring);
3687 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3689 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3690 if (r_glsl_permutation != perm)
3692 r_glsl_permutation = perm;
3693 if (!r_glsl_permutation->program)
3695 if (!r_glsl_permutation->compiled)
3696 R_GLSL_CompilePermutation(perm, mode, permutation);
3697 if (!r_glsl_permutation->program)
3699 // remove features until we find a valid permutation
3701 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3703 // reduce i more quickly whenever it would not remove any bits
3704 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3705 if (!(permutation & j))
3708 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3709 if (!r_glsl_permutation->compiled)
3710 R_GLSL_CompilePermutation(perm, mode, permutation);
3711 if (r_glsl_permutation->program)
3714 if (i >= SHADERPERMUTATION_COUNT)
3716 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3717 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3718 qglUseProgramObjectARB(0);CHECKGLERROR
3719 return; // no bit left to clear, entire mode is broken
3724 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3726 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3727 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3728 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3732 #include <Cg/cgGL.h>
3733 struct r_cg_permutation_s;
3734 typedef struct r_cg_permutation_s
3736 /// hash lookup data
3737 struct r_cg_permutation_s *hashnext;
3739 unsigned int permutation;
3741 /// indicates if we have tried compiling this permutation already
3743 /// 0 if compilation failed
3746 /// locations of detected parameters in programs, or NULL if not found
3747 CGparameter vp_EyePosition;
3748 CGparameter vp_FogPlane;
3749 CGparameter vp_LightDir;
3750 CGparameter vp_LightPosition;
3751 CGparameter vp_ModelToLight;
3752 CGparameter vp_TexMatrix;
3753 CGparameter vp_BackgroundTexMatrix;
3754 CGparameter vp_ModelViewProjectionMatrix;
3755 CGparameter vp_ModelViewMatrix;
3756 CGparameter vp_ShadowMapMatrix;
3758 CGparameter fp_Texture_First;
3759 CGparameter fp_Texture_Second;
3760 CGparameter fp_Texture_GammaRamps;
3761 CGparameter fp_Texture_Normal;
3762 CGparameter fp_Texture_Color;
3763 CGparameter fp_Texture_Gloss;
3764 CGparameter fp_Texture_Glow;
3765 CGparameter fp_Texture_SecondaryNormal;
3766 CGparameter fp_Texture_SecondaryColor;
3767 CGparameter fp_Texture_SecondaryGloss;
3768 CGparameter fp_Texture_SecondaryGlow;
3769 CGparameter fp_Texture_Pants;
3770 CGparameter fp_Texture_Shirt;
3771 CGparameter fp_Texture_FogMask;
3772 CGparameter fp_Texture_Lightmap;
3773 CGparameter fp_Texture_Deluxemap;
3774 CGparameter fp_Texture_Attenuation;
3775 CGparameter fp_Texture_Cube;
3776 CGparameter fp_Texture_Refraction;
3777 CGparameter fp_Texture_Reflection;
3778 CGparameter fp_Texture_ShadowMapRect;
3779 CGparameter fp_Texture_ShadowMapCube;
3780 CGparameter fp_Texture_ShadowMap2D;
3781 CGparameter fp_Texture_CubeProjection;
3782 CGparameter fp_Texture_ScreenDepth;
3783 CGparameter fp_Texture_ScreenNormalMap;
3784 CGparameter fp_Texture_ScreenDiffuse;
3785 CGparameter fp_Texture_ScreenSpecular;
3786 CGparameter fp_Texture_ReflectMask;
3787 CGparameter fp_Texture_ReflectCube;
3788 CGparameter fp_Alpha;
3789 CGparameter fp_BloomBlur_Parameters;
3790 CGparameter fp_ClientTime;
3791 CGparameter fp_Color_Ambient;
3792 CGparameter fp_Color_Diffuse;
3793 CGparameter fp_Color_Specular;
3794 CGparameter fp_Color_Glow;
3795 CGparameter fp_Color_Pants;
3796 CGparameter fp_Color_Shirt;
3797 CGparameter fp_DeferredColor_Ambient;
3798 CGparameter fp_DeferredColor_Diffuse;
3799 CGparameter fp_DeferredColor_Specular;
3800 CGparameter fp_DeferredMod_Diffuse;
3801 CGparameter fp_DeferredMod_Specular;
3802 CGparameter fp_DistortScaleRefractReflect;
3803 CGparameter fp_EyePosition;
3804 CGparameter fp_FogColor;
3805 CGparameter fp_FogHeightFade;
3806 CGparameter fp_FogPlane;
3807 CGparameter fp_FogPlaneViewDist;
3808 CGparameter fp_FogRangeRecip;
3809 CGparameter fp_LightColor;
3810 CGparameter fp_LightDir;
3811 CGparameter fp_LightPosition;
3812 CGparameter fp_OffsetMapping_Scale;
3813 CGparameter fp_PixelSize;
3814 CGparameter fp_ReflectColor;
3815 CGparameter fp_ReflectFactor;
3816 CGparameter fp_ReflectOffset;
3817 CGparameter fp_RefractColor;
3818 CGparameter fp_Saturation;
3819 CGparameter fp_ScreenCenterRefractReflect;
3820 CGparameter fp_ScreenScaleRefractReflect;
3821 CGparameter fp_ScreenToDepth;
3822 CGparameter fp_ShadowMap_Parameters;
3823 CGparameter fp_ShadowMap_TextureScale;
3824 CGparameter fp_SpecularPower;
3825 CGparameter fp_UserVec1;
3826 CGparameter fp_UserVec2;
3827 CGparameter fp_UserVec3;
3828 CGparameter fp_UserVec4;
3829 CGparameter fp_ViewTintColor;
3830 CGparameter fp_ViewToLight;
3831 CGparameter fp_PixelToScreenTexCoord;
3832 CGparameter fp_ModelToReflectCube;
3836 /// information about each possible shader permutation
3837 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3838 /// currently selected permutation
3839 r_cg_permutation_t *r_cg_permutation;
3840 /// storage for permutations linked in the hash table
3841 memexpandablearray_t r_cg_permutationarray;
3843 #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));}}
3845 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3847 //unsigned int hashdepth = 0;
3848 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3849 r_cg_permutation_t *p;
3850 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3852 if (p->mode == mode && p->permutation == permutation)
3854 //if (hashdepth > 10)
3855 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3860 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3862 p->permutation = permutation;
3863 p->hashnext = r_cg_permutationhash[mode][hashindex];
3864 r_cg_permutationhash[mode][hashindex] = p;
3865 //if (hashdepth > 10)
3866 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3870 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3873 if (!filename || !filename[0])
3875 if (!strcmp(filename, "cg/default.cg"))
3877 if (!cgshaderstring)
3879 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3881 Con_DPrintf("Loading shaders from file %s...\n", filename);
3883 cgshaderstring = (char *)builtincgshaderstring;
3885 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3886 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3887 return shaderstring;
3889 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3892 if (printfromdisknotice)
3893 Con_DPrintf("from disk %s... ", filename);
3894 return shaderstring;
3896 return shaderstring;
3899 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3901 // TODO: load or create .fp and .vp shader files
3904 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3907 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3908 int vertstrings_count = 0, vertstring_length = 0;
3909 int geomstrings_count = 0, geomstring_length = 0;
3910 int fragstrings_count = 0, fragstring_length = 0;
3912 char *vertexstring, *geometrystring, *fragmentstring;
3913 char *vertstring, *geomstring, *fragstring;
3914 const char *vertstrings_list[32+3];
3915 const char *geomstrings_list[32+3];
3916 const char *fragstrings_list[32+3];
3917 char permutationname[256];
3918 char cachename[256];
3919 CGprofile vertexProfile;
3920 CGprofile fragmentProfile;
3928 permutationname[0] = 0;
3930 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3931 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3932 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3934 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3935 strlcat(cachename, "cg/", sizeof(cachename));
3937 // the first pretext is which type of shader to compile as
3938 // (later these will all be bound together as a program object)
3939 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3940 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3941 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3943 // the second pretext is the mode (for example a light source)
3944 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3945 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3946 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3947 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3948 strlcat(cachename, modeinfo->name, sizeof(cachename));
3950 // now add all the permutation pretexts
3951 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3953 if (permutation & (1<<i))
3955 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3956 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3957 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3958 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3959 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3963 // keep line numbers correct
3964 vertstrings_list[vertstrings_count++] = "\n";
3965 geomstrings_list[geomstrings_count++] = "\n";
3966 fragstrings_list[fragstrings_count++] = "\n";
3970 // replace spaces in the cachename with _ characters
3971 for (i = 0;cachename[i];i++)
3972 if (cachename[i] == ' ')
3975 // now append the shader text itself
3976 vertstrings_list[vertstrings_count++] = vertexstring;
3977 geomstrings_list[geomstrings_count++] = geometrystring;
3978 fragstrings_list[fragstrings_count++] = fragmentstring;
3980 // if any sources were NULL, clear the respective list
3982 vertstrings_count = 0;
3983 if (!geometrystring)
3984 geomstrings_count = 0;
3985 if (!fragmentstring)
3986 fragstrings_count = 0;
3988 vertstring_length = 0;
3989 for (i = 0;i < vertstrings_count;i++)
3990 vertstring_length += strlen(vertstrings_list[i]);
3991 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3992 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3993 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3995 geomstring_length = 0;
3996 for (i = 0;i < geomstrings_count;i++)
3997 geomstring_length += strlen(geomstrings_list[i]);
3998 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3999 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4000 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4002 fragstring_length = 0;
4003 for (i = 0;i < fragstrings_count;i++)
4004 fragstring_length += strlen(fragstrings_list[i]);
4005 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4006 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4007 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4011 //vertexProfile = CG_PROFILE_ARBVP1;
4012 //fragmentProfile = CG_PROFILE_ARBFP1;
4013 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4014 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4015 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4016 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4017 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4020 // try to load the cached shader, or generate one
4021 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4023 // if caching failed, do a dynamic compile for now
4025 if (vertstring[0] && !p->vprogram)
4026 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4028 if (fragstring[0] && !p->fprogram)
4029 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4032 // look up all the uniform variable names we care about, so we don't
4033 // have to look them up every time we set them
4037 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4038 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4039 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4040 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4041 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4042 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4043 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4044 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4045 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4046 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4047 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4048 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4054 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4055 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4056 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4057 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4058 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4059 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4060 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4061 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4062 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4063 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4064 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4065 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4066 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4067 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4068 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4069 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4070 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4071 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4072 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4073 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4074 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4075 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4076 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4077 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4078 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4079 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4080 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4081 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4082 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4083 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4084 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4085 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4086 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4087 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4088 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4089 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4090 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4091 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4092 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4093 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4094 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4095 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4096 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4097 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4098 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4099 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4100 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4101 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4102 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4103 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4104 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4105 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4106 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4107 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4108 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4109 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4110 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4111 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4112 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4113 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4114 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4115 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4116 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4117 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4118 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4119 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4120 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4121 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4122 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4123 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4124 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4125 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4126 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4127 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4128 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4129 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4130 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4134 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4135 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4137 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4141 Mem_Free(vertstring);
4143 Mem_Free(geomstring);
4145 Mem_Free(fragstring);
4147 Mem_Free(vertexstring);
4149 Mem_Free(geometrystring);
4151 Mem_Free(fragmentstring);
4154 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4156 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4159 if (r_cg_permutation != perm)
4161 r_cg_permutation = perm;
4162 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4164 if (!r_cg_permutation->compiled)
4165 R_CG_CompilePermutation(perm, mode, permutation);
4166 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4168 // remove features until we find a valid permutation
4170 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4172 // reduce i more quickly whenever it would not remove any bits
4173 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4174 if (!(permutation & j))
4177 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4178 if (!r_cg_permutation->compiled)
4179 R_CG_CompilePermutation(perm, mode, permutation);
4180 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4183 if (i >= SHADERPERMUTATION_COUNT)
4185 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4186 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4187 return; // no bit left to clear, entire mode is broken
4193 if (r_cg_permutation->vprogram)
4195 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4196 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4197 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4201 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4202 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4204 if (r_cg_permutation->fprogram)
4206 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4207 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4208 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4212 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4213 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4217 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4218 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4219 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4222 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4224 cgGLSetTextureParameter(param, R_GetTexture(tex));
4225 cgGLEnableTextureParameter(param);
4229 void R_GLSL_Restart_f(void)
4231 unsigned int i, limit;
4232 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4233 Mem_Free(glslshaderstring);
4234 glslshaderstring = NULL;
4235 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4236 Mem_Free(cgshaderstring);
4237 cgshaderstring = NULL;
4238 switch(vid.renderpath)
4240 case RENDERPATH_GL20:
4242 r_glsl_permutation_t *p;
4243 r_glsl_permutation = NULL;
4244 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4245 for (i = 0;i < limit;i++)
4247 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4249 GL_Backend_FreeProgram(p->program);
4250 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4253 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4256 case RENDERPATH_CGGL:
4259 r_cg_permutation_t *p;
4260 r_cg_permutation = NULL;
4261 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4262 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4263 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4264 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4265 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4266 for (i = 0;i < limit;i++)
4268 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4271 cgDestroyProgram(p->vprogram);
4273 cgDestroyProgram(p->fprogram);
4274 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4277 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4281 case RENDERPATH_GL13:
4282 case RENDERPATH_GL11:
4287 void R_GLSL_DumpShader_f(void)
4292 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4295 FS_Print(file, "/* The engine may define the following macros:\n");
4296 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4297 for (i = 0;i < SHADERMODE_COUNT;i++)
4298 FS_Print(file, glslshadermodeinfo[i].pretext);
4299 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4300 FS_Print(file, shaderpermutationinfo[i].pretext);
4301 FS_Print(file, "*/\n");
4302 FS_Print(file, builtinshaderstring);
4304 Con_Printf("glsl/default.glsl written\n");
4307 Con_Printf("failed to write to glsl/default.glsl\n");
4310 file = FS_OpenRealFile("cg/default.cg", "w", false);
4313 FS_Print(file, "/* The engine may define the following macros:\n");
4314 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4315 for (i = 0;i < SHADERMODE_COUNT;i++)
4316 FS_Print(file, cgshadermodeinfo[i].pretext);
4317 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4318 FS_Print(file, shaderpermutationinfo[i].pretext);
4319 FS_Print(file, "*/\n");
4320 FS_Print(file, builtincgshaderstring);
4322 Con_Printf("cg/default.cg written\n");
4325 Con_Printf("failed to write to cg/default.cg\n");
4329 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4332 texturemode = GL_MODULATE;
4333 switch (vid.renderpath)
4335 case RENDERPATH_GL20:
4336 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))));
4337 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4338 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4340 case RENDERPATH_CGGL:
4343 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))));
4344 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4345 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4348 case RENDERPATH_GL13:
4349 R_Mesh_TexBind(0, first );
4350 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4351 R_Mesh_TexBind(1, second);
4353 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4355 case RENDERPATH_GL11:
4356 R_Mesh_TexBind(0, first );
4361 void R_SetupShader_DepthOrShadow(void)
4363 switch (vid.renderpath)
4365 case RENDERPATH_GL20:
4366 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4368 case RENDERPATH_CGGL:
4370 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4373 case RENDERPATH_GL13:
4374 R_Mesh_TexBind(0, 0);
4375 R_Mesh_TexBind(1, 0);
4377 case RENDERPATH_GL11:
4378 R_Mesh_TexBind(0, 0);
4383 void R_SetupShader_ShowDepth(void)
4385 switch (vid.renderpath)
4387 case RENDERPATH_GL20:
4388 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4390 case RENDERPATH_CGGL:
4392 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4395 case RENDERPATH_GL13:
4397 case RENDERPATH_GL11:
4402 extern qboolean r_shadow_usingdeferredprepass;
4403 extern cvar_t r_shadow_deferred_8bitrange;
4404 extern rtexture_t *r_shadow_attenuationgradienttexture;
4405 extern rtexture_t *r_shadow_attenuation2dtexture;
4406 extern rtexture_t *r_shadow_attenuation3dtexture;
4407 extern qboolean r_shadow_usingshadowmaprect;
4408 extern qboolean r_shadow_usingshadowmapcube;
4409 extern qboolean r_shadow_usingshadowmap2d;
4410 extern qboolean r_shadow_usingshadowmaportho;
4411 extern float r_shadow_shadowmap_texturescale[2];
4412 extern float r_shadow_shadowmap_parameters[4];
4413 extern qboolean r_shadow_shadowmapvsdct;
4414 extern qboolean r_shadow_shadowmapsampler;
4415 extern int r_shadow_shadowmappcf;
4416 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4417 extern rtexture_t *r_shadow_shadowmap2dtexture;
4418 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4419 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4420 extern matrix4x4_t r_shadow_shadowmapmatrix;
4421 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4422 extern int r_shadow_prepass_width;
4423 extern int r_shadow_prepass_height;
4424 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4425 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4426 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4427 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4428 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4430 // select a permutation of the lighting shader appropriate to this
4431 // combination of texture, entity, light source, and fogging, only use the
4432 // minimum features necessary to avoid wasting rendering time in the
4433 // fragment shader on features that are not being used
4434 unsigned int permutation = 0;
4435 unsigned int mode = 0;
4437 if (rsurfacepass == RSURFPASS_BACKGROUND)
4439 // distorted background
4440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4441 mode = SHADERMODE_WATER;
4443 mode = SHADERMODE_REFRACTION;
4444 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4445 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4446 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4447 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4448 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4449 R_Mesh_ColorPointer(NULL, 0, 0);
4450 GL_AlphaTest(false);
4451 GL_BlendFunc(GL_ONE, GL_ZERO);
4453 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4455 if (r_glsl_offsetmapping.integer)
4457 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4458 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4459 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4460 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4461 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4463 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4464 if (r_glsl_offsetmapping_reliefmapping.integer)
4465 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4469 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4470 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4471 permutation |= SHADERPERMUTATION_ALPHAKILL;
4472 // normalmap (deferred prepass), may use alpha test on diffuse
4473 mode = SHADERMODE_DEFERREDGEOMETRY;
4474 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4475 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4476 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4477 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4478 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4479 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4480 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4481 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4482 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4484 R_Mesh_ColorPointer(NULL, 0, 0);
4485 GL_AlphaTest(false);
4486 GL_BlendFunc(GL_ONE, GL_ZERO);
4488 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4490 if (r_glsl_offsetmapping.integer)
4492 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4493 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4494 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4495 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4496 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4498 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4499 if (r_glsl_offsetmapping_reliefmapping.integer)
4500 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4503 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4504 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4506 mode = SHADERMODE_LIGHTSOURCE;
4507 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4508 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4509 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4510 permutation |= SHADERPERMUTATION_CUBEFILTER;
4511 if (diffusescale > 0)
4512 permutation |= SHADERPERMUTATION_DIFFUSE;
4513 if (specularscale > 0)
4515 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4516 if (r_shadow_glossexact.integer)
4517 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4519 if (r_refdef.fogenabled)
4520 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4521 if (rsurface.texture->colormapping)
4522 permutation |= SHADERPERMUTATION_COLORMAPPING;
4523 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4525 if (r_shadow_usingshadowmaprect)
4526 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4527 if (r_shadow_usingshadowmap2d)
4528 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4529 if (r_shadow_usingshadowmapcube)
4530 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4531 else if(r_shadow_shadowmapvsdct)
4532 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4534 if (r_shadow_shadowmapsampler)
4535 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4536 if (r_shadow_shadowmappcf > 1)
4537 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4538 else if (r_shadow_shadowmappcf)
4539 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4541 if (rsurface.texture->reflectmasktexture)
4542 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4543 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4544 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4546 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4547 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4548 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4552 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4553 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4554 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4556 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4557 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4558 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4560 R_Mesh_ColorPointer(NULL, 0, 0);
4561 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4562 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4564 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4566 if (r_glsl_offsetmapping.integer)
4568 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4569 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4570 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4571 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4572 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4574 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4575 if (r_glsl_offsetmapping_reliefmapping.integer)
4576 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4579 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4580 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4581 // unshaded geometry (fullbright or ambient model lighting)
4582 mode = SHADERMODE_FLATCOLOR;
4583 ambientscale = diffusescale = specularscale = 0;
4584 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4585 permutation |= SHADERPERMUTATION_GLOW;
4586 if (r_refdef.fogenabled)
4587 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4588 if (rsurface.texture->colormapping)
4589 permutation |= SHADERPERMUTATION_COLORMAPPING;
4590 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4592 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4593 if (r_shadow_usingshadowmaprect)
4594 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4595 if (r_shadow_usingshadowmap2d)
4596 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4598 if (r_shadow_shadowmapsampler)
4599 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4600 if (r_shadow_shadowmappcf > 1)
4601 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4602 else if (r_shadow_shadowmappcf)
4603 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4605 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4606 permutation |= SHADERPERMUTATION_REFLECTION;
4607 if (rsurface.texture->reflectmasktexture)
4608 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4609 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4610 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4612 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4613 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4614 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4618 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4619 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4620 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4622 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4623 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4624 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4626 R_Mesh_ColorPointer(NULL, 0, 0);
4627 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4628 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4630 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4632 if (r_glsl_offsetmapping.integer)
4634 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4635 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4636 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4637 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4638 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4640 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4641 if (r_glsl_offsetmapping_reliefmapping.integer)
4642 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4645 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4646 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4647 // directional model lighting
4648 mode = SHADERMODE_LIGHTDIRECTION;
4649 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4650 permutation |= SHADERPERMUTATION_GLOW;
4651 permutation |= SHADERPERMUTATION_DIFFUSE;
4652 if (specularscale > 0)
4654 permutation |= SHADERPERMUTATION_SPECULAR;
4655 if (r_shadow_glossexact.integer)
4656 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4658 if (r_refdef.fogenabled)
4659 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4660 if (rsurface.texture->colormapping)
4661 permutation |= SHADERPERMUTATION_COLORMAPPING;
4662 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4664 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4665 if (r_shadow_usingshadowmaprect)
4666 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4667 if (r_shadow_usingshadowmap2d)
4668 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4670 if (r_shadow_shadowmapsampler)
4671 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4672 if (r_shadow_shadowmappcf > 1)
4673 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4674 else if (r_shadow_shadowmappcf)
4675 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4677 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4678 permutation |= SHADERPERMUTATION_REFLECTION;
4679 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4680 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4681 if (rsurface.texture->reflectmasktexture)
4682 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4683 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4684 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4686 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4687 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4688 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4692 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4693 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4694 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4696 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4697 R_Mesh_ColorPointer(NULL, 0, 0);
4698 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4699 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4701 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4703 if (r_glsl_offsetmapping.integer)
4705 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4706 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4707 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4708 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4709 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4711 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4712 if (r_glsl_offsetmapping_reliefmapping.integer)
4713 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4716 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4717 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4718 // ambient model lighting
4719 mode = SHADERMODE_LIGHTDIRECTION;
4720 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4721 permutation |= SHADERPERMUTATION_GLOW;
4722 if (r_refdef.fogenabled)
4723 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4724 if (rsurface.texture->colormapping)
4725 permutation |= SHADERPERMUTATION_COLORMAPPING;
4726 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4728 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4729 if (r_shadow_usingshadowmaprect)
4730 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4731 if (r_shadow_usingshadowmap2d)
4732 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4734 if (r_shadow_shadowmapsampler)
4735 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4736 if (r_shadow_shadowmappcf > 1)
4737 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4738 else if (r_shadow_shadowmappcf)
4739 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4741 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4742 permutation |= SHADERPERMUTATION_REFLECTION;
4743 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4744 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4745 if (rsurface.texture->reflectmasktexture)
4746 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4747 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4748 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4750 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4751 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4752 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4756 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4757 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4758 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4760 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4761 R_Mesh_ColorPointer(NULL, 0, 0);
4762 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4763 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4767 if (r_glsl_offsetmapping.integer)
4769 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4770 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4771 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4772 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4773 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4775 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4776 if (r_glsl_offsetmapping_reliefmapping.integer)
4777 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4780 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4781 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4783 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4784 permutation |= SHADERPERMUTATION_GLOW;
4785 if (r_refdef.fogenabled)
4786 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4787 if (rsurface.texture->colormapping)
4788 permutation |= SHADERPERMUTATION_COLORMAPPING;
4789 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4791 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4792 if (r_shadow_usingshadowmaprect)
4793 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4794 if (r_shadow_usingshadowmap2d)
4795 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4797 if (r_shadow_shadowmapsampler)
4798 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4799 if (r_shadow_shadowmappcf > 1)
4800 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4801 else if (r_shadow_shadowmappcf)
4802 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4804 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4805 permutation |= SHADERPERMUTATION_REFLECTION;
4806 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4807 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4808 if (rsurface.texture->reflectmasktexture)
4809 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4810 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4812 // deluxemapping (light direction texture)
4813 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4814 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4816 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4817 permutation |= SHADERPERMUTATION_DIFFUSE;
4818 if (specularscale > 0)
4820 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4821 if (r_shadow_glossexact.integer)
4822 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4824 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4825 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4826 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4828 R_Mesh_ColorPointer(NULL, 0, 0);
4830 else if (r_glsl_deluxemapping.integer >= 2)
4832 // fake deluxemapping (uniform light direction in tangentspace)
4833 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4834 permutation |= SHADERPERMUTATION_DIFFUSE;
4835 if (specularscale > 0)
4837 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4838 if (r_shadow_glossexact.integer)
4839 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4841 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4843 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4845 R_Mesh_ColorPointer(NULL, 0, 0);
4847 else if (rsurface.uselightmaptexture)
4849 // ordinary lightmapping (q1bsp, q3bsp)
4850 mode = SHADERMODE_LIGHTMAP;
4851 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4852 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4853 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4855 R_Mesh_ColorPointer(NULL, 0, 0);
4859 // ordinary vertex coloring (q3bsp)
4860 mode = SHADERMODE_VERTEXCOLOR;
4861 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4862 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4864 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4865 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4867 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4868 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4869 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4873 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4874 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4875 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4877 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4878 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4880 switch(vid.renderpath)
4882 case RENDERPATH_GL20:
4883 R_SetupShader_SetPermutationGLSL(mode, permutation);
4884 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4885 if (mode == SHADERMODE_LIGHTSOURCE)
4887 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4888 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4889 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4890 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);
4891 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);
4892 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);
4894 // additive passes are only darkened by fog, not tinted
4895 if (r_glsl_permutation->loc_FogColor >= 0)
4896 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4897 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4901 if (mode == SHADERMODE_FLATCOLOR)
4903 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4905 else if (mode == SHADERMODE_LIGHTDIRECTION)
4907 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]);
4908 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]);
4909 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);
4910 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);
4911 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);
4912 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]);
4913 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]);
4917 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]);
4918 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]);
4919 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);
4920 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);
4921 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);
4923 // additive passes are only darkened by fog, not tinted
4924 if (r_glsl_permutation->loc_FogColor >= 0)
4926 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4927 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4929 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4931 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);
4932 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]);
4933 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]);
4934 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4935 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4936 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4937 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4938 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4940 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4941 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4942 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4943 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]);
4944 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]);
4946 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4947 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4948 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4949 if (r_glsl_permutation->loc_Color_Pants >= 0)
4951 if (rsurface.texture->pantstexture)
4952 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4954 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4956 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4958 if (rsurface.texture->shirttexture)
4959 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4961 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4963 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]);
4964 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4965 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4966 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4967 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
4968 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]);
4969 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4971 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4972 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4973 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4974 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4975 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4976 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4977 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4978 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4979 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4980 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4981 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4982 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4983 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4984 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
4985 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4986 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4987 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4988 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4989 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4990 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4991 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4992 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4993 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4994 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4995 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4996 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4998 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
4999 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
5000 if (rsurface.rtlight)
5002 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5003 if (r_shadow_usingshadowmapcube)
5004 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5005 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5010 case RENDERPATH_CGGL:
5012 R_SetupShader_SetPermutationCG(mode, permutation);
5013 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5014 if (mode == SHADERMODE_LIGHTSOURCE)
5016 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5017 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5021 if (mode == SHADERMODE_LIGHTDIRECTION)
5023 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
5026 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5027 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5028 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5029 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5030 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
5033 if (mode == SHADERMODE_LIGHTSOURCE)
5035 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5036 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5037 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
5038 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
5039 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
5041 // additive passes are only darkened by fog, not tinted
5042 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5043 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5047 if (mode == SHADERMODE_FLATCOLOR)
5049 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5051 else if (mode == SHADERMODE_LIGHTDIRECTION)
5053 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
5054 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
5055 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
5056 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
5057 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
5058 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
5059 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
5063 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
5064 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
5065 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
5066 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
5067 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
5069 // additive passes are only darkened by fog, not tinted
5070 if (r_cg_permutation->fp_FogColor)
5072 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5073 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5075 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5078 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
5079 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
5080 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
5081 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5082 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5083 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5084 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5085 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5087 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
5088 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
5089 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5090 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5091 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5092 if (r_cg_permutation->fp_Color_Pants)
5094 if (rsurface.texture->pantstexture)
5095 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5097 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5100 if (r_cg_permutation->fp_Color_Shirt)
5102 if (rsurface.texture->shirttexture)
5103 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5105 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5108 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
5109 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5110 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5111 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5112 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5113 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
5114 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5116 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5117 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5118 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5119 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5120 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5121 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5122 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5123 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5124 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5125 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5126 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5127 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5128 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5129 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5130 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
5131 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5132 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5133 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5134 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5135 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5136 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5137 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5138 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5139 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5140 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5141 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5143 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5144 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5145 if (rsurface.rtlight)
5147 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5148 if (r_shadow_usingshadowmapcube)
5149 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5150 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5157 case RENDERPATH_GL13:
5158 case RENDERPATH_GL11:
5163 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5165 // select a permutation of the lighting shader appropriate to this
5166 // combination of texture, entity, light source, and fogging, only use the
5167 // minimum features necessary to avoid wasting rendering time in the
5168 // fragment shader on features that are not being used
5169 unsigned int permutation = 0;
5170 unsigned int mode = 0;
5171 const float *lightcolorbase = rtlight->currentcolor;
5172 float ambientscale = rtlight->ambientscale;
5173 float diffusescale = rtlight->diffusescale;
5174 float specularscale = rtlight->specularscale;
5175 // this is the location of the light in view space
5176 vec3_t viewlightorigin;
5177 // this transforms from view space (camera) to light space (cubemap)
5178 matrix4x4_t viewtolight;
5179 matrix4x4_t lighttoview;
5180 float viewtolight16f[16];
5181 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5183 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5184 if (rtlight->currentcubemap != r_texture_whitecube)
5185 permutation |= SHADERPERMUTATION_CUBEFILTER;
5186 if (diffusescale > 0)
5187 permutation |= SHADERPERMUTATION_DIFFUSE;
5188 if (specularscale > 0)
5190 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5191 if (r_shadow_glossexact.integer)
5192 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5194 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5196 if (r_shadow_usingshadowmaprect)
5197 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5198 if (r_shadow_usingshadowmap2d)
5199 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5200 if (r_shadow_usingshadowmapcube)
5201 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5202 else if(r_shadow_shadowmapvsdct)
5203 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5205 if (r_shadow_shadowmapsampler)
5206 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5207 if (r_shadow_shadowmappcf > 1)
5208 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5209 else if (r_shadow_shadowmappcf)
5210 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5212 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5213 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5214 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5215 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5216 switch(vid.renderpath)
5218 case RENDERPATH_GL20:
5219 R_SetupShader_SetPermutationGLSL(mode, permutation);
5220 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5221 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5222 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);
5223 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);
5224 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);
5225 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]);
5226 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]);
5227 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));
5228 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]);
5229 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5231 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5232 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5233 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5234 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5235 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5236 if (r_shadow_usingshadowmapcube)
5237 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5238 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5239 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5241 case RENDERPATH_CGGL:
5243 R_SetupShader_SetPermutationCG(mode, permutation);
5244 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5245 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5246 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
5247 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
5248 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
5249 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
5250 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
5251 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
5252 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
5253 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5255 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5256 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5257 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5258 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5259 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5260 if (r_shadow_usingshadowmapcube)
5261 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5262 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5263 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5266 case RENDERPATH_GL13:
5267 case RENDERPATH_GL11:
5272 #define SKINFRAME_HASH 1024
5276 int loadsequence; // incremented each level change
5277 memexpandablearray_t array;
5278 skinframe_t *hash[SKINFRAME_HASH];
5281 r_skinframe_t r_skinframe;
5283 void R_SkinFrame_PrepareForPurge(void)
5285 r_skinframe.loadsequence++;
5286 // wrap it without hitting zero
5287 if (r_skinframe.loadsequence >= 200)
5288 r_skinframe.loadsequence = 1;
5291 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5295 // mark the skinframe as used for the purging code
5296 skinframe->loadsequence = r_skinframe.loadsequence;
5299 void R_SkinFrame_Purge(void)
5303 for (i = 0;i < SKINFRAME_HASH;i++)
5305 for (s = r_skinframe.hash[i];s;s = s->next)
5307 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5309 if (s->merged == s->base)
5311 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5312 R_PurgeTexture(s->stain );s->stain = NULL;
5313 R_PurgeTexture(s->merged);s->merged = NULL;
5314 R_PurgeTexture(s->base );s->base = NULL;
5315 R_PurgeTexture(s->pants );s->pants = NULL;
5316 R_PurgeTexture(s->shirt );s->shirt = NULL;
5317 R_PurgeTexture(s->nmap );s->nmap = NULL;
5318 R_PurgeTexture(s->gloss );s->gloss = NULL;
5319 R_PurgeTexture(s->glow );s->glow = NULL;
5320 R_PurgeTexture(s->fog );s->fog = NULL;
5321 R_PurgeTexture(s->reflect);s->reflect = NULL;
5322 s->loadsequence = 0;
5328 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5330 char basename[MAX_QPATH];
5332 Image_StripImageExtension(name, basename, sizeof(basename));
5334 if( last == NULL ) {
5336 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5337 item = r_skinframe.hash[hashindex];
5342 // linearly search through the hash bucket
5343 for( ; item ; item = item->next ) {
5344 if( !strcmp( item->basename, basename ) ) {
5351 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5355 char basename[MAX_QPATH];
5357 Image_StripImageExtension(name, basename, sizeof(basename));
5359 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5360 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5361 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5365 rtexture_t *dyntexture;
5366 // check whether its a dynamic texture
5367 dyntexture = CL_GetDynTexture( basename );
5368 if (!add && !dyntexture)
5370 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5371 memset(item, 0, sizeof(*item));
5372 strlcpy(item->basename, basename, sizeof(item->basename));
5373 item->base = dyntexture; // either NULL or dyntexture handle
5374 item->textureflags = textureflags;
5375 item->comparewidth = comparewidth;
5376 item->compareheight = compareheight;
5377 item->comparecrc = comparecrc;
5378 item->next = r_skinframe.hash[hashindex];
5379 r_skinframe.hash[hashindex] = item;
5381 else if( item->base == NULL )
5383 rtexture_t *dyntexture;
5384 // check whether its a dynamic texture
5385 // 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]
5386 dyntexture = CL_GetDynTexture( basename );
5387 item->base = dyntexture; // either NULL or dyntexture handle
5390 R_SkinFrame_MarkUsed(item);
5394 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5396 unsigned long long avgcolor[5], wsum; \
5404 for(pix = 0; pix < cnt; ++pix) \
5407 for(comp = 0; comp < 3; ++comp) \
5409 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5412 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5414 for(comp = 0; comp < 3; ++comp) \
5415 avgcolor[comp] += getpixel * w; \
5418 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5419 avgcolor[4] += getpixel; \
5421 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5423 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5424 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5425 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5426 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5429 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5432 unsigned char *pixels;
5433 unsigned char *bumppixels;
5434 unsigned char *basepixels = NULL;
5435 int basepixels_width = 0;
5436 int basepixels_height = 0;
5437 skinframe_t *skinframe;
5438 rtexture_t *ddsbase = NULL;
5439 qboolean ddshasalpha = false;
5440 float ddsavgcolor[4];
5441 char basename[MAX_QPATH];
5443 if (cls.state == ca_dedicated)
5446 // return an existing skinframe if already loaded
5447 // if loading of the first image fails, don't make a new skinframe as it
5448 // would cause all future lookups of this to be missing
5449 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5450 if (skinframe && skinframe->base)
5453 Image_StripImageExtension(name, basename, sizeof(basename));
5455 // check for DDS texture file first
5456 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5458 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5459 if (basepixels == NULL)
5463 if (developer_loading.integer)
5464 Con_Printf("loading skin \"%s\"\n", name);
5466 // we've got some pixels to store, so really allocate this new texture now
5468 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5469 skinframe->stain = NULL;
5470 skinframe->merged = NULL;
5471 skinframe->base = NULL;
5472 skinframe->pants = NULL;
5473 skinframe->shirt = NULL;
5474 skinframe->nmap = NULL;
5475 skinframe->gloss = NULL;
5476 skinframe->glow = NULL;
5477 skinframe->fog = NULL;
5478 skinframe->reflect = NULL;
5479 skinframe->hasalpha = false;
5483 skinframe->base = ddsbase;
5484 skinframe->hasalpha = ddshasalpha;
5485 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5486 if (r_loadfog && skinframe->hasalpha)
5487 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5488 //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]);
5492 basepixels_width = image_width;
5493 basepixels_height = image_height;
5494 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);
5495 if (textureflags & TEXF_ALPHA)
5497 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5499 if (basepixels[j] < 255)
5501 skinframe->hasalpha = true;
5505 if (r_loadfog && skinframe->hasalpha)
5507 // has transparent pixels
5508 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5509 for (j = 0;j < image_width * image_height * 4;j += 4)
5514 pixels[j+3] = basepixels[j+3];
5516 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);
5520 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5521 //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]);
5522 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5523 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5524 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5525 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5530 if (r_loadnormalmap)
5531 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5532 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5534 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5535 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5536 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5537 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5540 // _norm is the name used by tenebrae and has been adopted as standard
5541 if (r_loadnormalmap && skinframe->nmap == NULL)
5543 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5545 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);
5549 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5551 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5552 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5553 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);
5555 Mem_Free(bumppixels);
5557 else if (r_shadow_bumpscale_basetexture.value > 0)
5559 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5560 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5561 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);
5564 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5565 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5568 // _luma is supported only for tenebrae compatibility
5569 // _glow is the preferred name
5570 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))))
5572 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);
5573 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5574 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5575 Mem_Free(pixels);pixels = NULL;
5578 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5580 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);
5581 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5582 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5587 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5589 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);
5590 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5591 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5596 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5598 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);
5599 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5600 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5605 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5607 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);
5608 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5609 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5615 Mem_Free(basepixels);
5620 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5621 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5624 unsigned char *temp1, *temp2;
5625 skinframe_t *skinframe;
5627 if (cls.state == ca_dedicated)
5630 // if already loaded just return it, otherwise make a new skinframe
5631 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5632 if (skinframe && skinframe->base)
5635 skinframe->stain = NULL;
5636 skinframe->merged = NULL;
5637 skinframe->base = NULL;
5638 skinframe->pants = NULL;
5639 skinframe->shirt = NULL;
5640 skinframe->nmap = NULL;
5641 skinframe->gloss = NULL;
5642 skinframe->glow = NULL;
5643 skinframe->fog = NULL;
5644 skinframe->reflect = NULL;
5645 skinframe->hasalpha = false;
5647 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5651 if (developer_loading.integer)
5652 Con_Printf("loading 32bit skin \"%s\"\n", name);
5654 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5656 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5657 temp2 = temp1 + width * height * 4;
5658 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5659 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5662 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5663 if (textureflags & TEXF_ALPHA)
5665 for (i = 3;i < width * height * 4;i += 4)
5667 if (skindata[i] < 255)
5669 skinframe->hasalpha = true;
5673 if (r_loadfog && skinframe->hasalpha)
5675 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5676 memcpy(fogpixels, skindata, width * height * 4);
5677 for (i = 0;i < width * height * 4;i += 4)
5678 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5679 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5680 Mem_Free(fogpixels);
5684 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5685 //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]);
5690 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5694 skinframe_t *skinframe;
5696 if (cls.state == ca_dedicated)
5699 // if already loaded just return it, otherwise make a new skinframe
5700 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5701 if (skinframe && skinframe->base)
5704 skinframe->stain = NULL;
5705 skinframe->merged = NULL;
5706 skinframe->base = NULL;
5707 skinframe->pants = NULL;
5708 skinframe->shirt = NULL;
5709 skinframe->nmap = NULL;
5710 skinframe->gloss = NULL;
5711 skinframe->glow = NULL;
5712 skinframe->fog = NULL;
5713 skinframe->reflect = NULL;
5714 skinframe->hasalpha = false;
5716 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5720 if (developer_loading.integer)
5721 Con_Printf("loading quake skin \"%s\"\n", name);
5723 // 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)
5724 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5725 memcpy(skinframe->qpixels, skindata, width*height);
5726 skinframe->qwidth = width;
5727 skinframe->qheight = height;
5730 for (i = 0;i < width * height;i++)
5731 featuresmask |= palette_featureflags[skindata[i]];
5733 skinframe->hasalpha = false;
5734 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5735 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5736 skinframe->qgeneratemerged = true;
5737 skinframe->qgeneratebase = skinframe->qhascolormapping;
5738 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5740 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5741 //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]);
5746 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5750 unsigned char *skindata;
5752 if (!skinframe->qpixels)
5755 if (!skinframe->qhascolormapping)
5756 colormapped = false;
5760 if (!skinframe->qgeneratebase)
5765 if (!skinframe->qgeneratemerged)
5769 width = skinframe->qwidth;
5770 height = skinframe->qheight;
5771 skindata = skinframe->qpixels;
5773 if (skinframe->qgeneratenmap)
5775 unsigned char *temp1, *temp2;
5776 skinframe->qgeneratenmap = false;
5777 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5778 temp2 = temp1 + width * height * 4;
5779 // use either a custom palette or the quake palette
5780 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5781 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5782 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5786 if (skinframe->qgenerateglow)
5788 skinframe->qgenerateglow = false;
5789 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5794 skinframe->qgeneratebase = false;
5795 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);
5796 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5797 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5801 skinframe->qgeneratemerged = false;
5802 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5805 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5807 Mem_Free(skinframe->qpixels);
5808 skinframe->qpixels = NULL;
5812 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)
5815 skinframe_t *skinframe;
5817 if (cls.state == ca_dedicated)
5820 // if already loaded just return it, otherwise make a new skinframe
5821 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5822 if (skinframe && skinframe->base)
5825 skinframe->stain = NULL;
5826 skinframe->merged = NULL;
5827 skinframe->base = NULL;
5828 skinframe->pants = NULL;
5829 skinframe->shirt = NULL;
5830 skinframe->nmap = NULL;
5831 skinframe->gloss = NULL;
5832 skinframe->glow = NULL;
5833 skinframe->fog = NULL;
5834 skinframe->reflect = NULL;
5835 skinframe->hasalpha = false;
5837 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5841 if (developer_loading.integer)
5842 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5844 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5845 if (textureflags & TEXF_ALPHA)
5847 for (i = 0;i < width * height;i++)
5849 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5851 skinframe->hasalpha = true;
5855 if (r_loadfog && skinframe->hasalpha)
5856 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5859 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5860 //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]);
5865 skinframe_t *R_SkinFrame_LoadMissing(void)
5867 skinframe_t *skinframe;
5869 if (cls.state == ca_dedicated)
5872 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5873 skinframe->stain = NULL;
5874 skinframe->merged = NULL;
5875 skinframe->base = NULL;
5876 skinframe->pants = NULL;
5877 skinframe->shirt = NULL;
5878 skinframe->nmap = NULL;
5879 skinframe->gloss = NULL;
5880 skinframe->glow = NULL;
5881 skinframe->fog = NULL;
5882 skinframe->reflect = NULL;
5883 skinframe->hasalpha = false;
5885 skinframe->avgcolor[0] = rand() / RAND_MAX;
5886 skinframe->avgcolor[1] = rand() / RAND_MAX;
5887 skinframe->avgcolor[2] = rand() / RAND_MAX;
5888 skinframe->avgcolor[3] = 1;
5893 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5894 typedef struct suffixinfo_s
5897 qboolean flipx, flipy, flipdiagonal;
5900 static suffixinfo_t suffix[3][6] =
5903 {"px", false, false, false},
5904 {"nx", false, false, false},
5905 {"py", false, false, false},
5906 {"ny", false, false, false},
5907 {"pz", false, false, false},
5908 {"nz", false, false, false}
5911 {"posx", false, false, false},
5912 {"negx", false, false, false},
5913 {"posy", false, false, false},
5914 {"negy", false, false, false},
5915 {"posz", false, false, false},
5916 {"negz", false, false, false}
5919 {"rt", true, false, true},
5920 {"lf", false, true, true},
5921 {"ft", true, true, false},
5922 {"bk", false, false, false},
5923 {"up", true, false, true},
5924 {"dn", true, false, true}
5928 static int componentorder[4] = {0, 1, 2, 3};
5930 rtexture_t *R_LoadCubemap(const char *basename)
5932 int i, j, cubemapsize;
5933 unsigned char *cubemappixels, *image_buffer;
5934 rtexture_t *cubemaptexture;
5936 // must start 0 so the first loadimagepixels has no requested width/height
5938 cubemappixels = NULL;
5939 cubemaptexture = NULL;
5940 // keep trying different suffix groups (posx, px, rt) until one loads
5941 for (j = 0;j < 3 && !cubemappixels;j++)
5943 // load the 6 images in the suffix group
5944 for (i = 0;i < 6;i++)
5946 // generate an image name based on the base and and suffix
5947 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5949 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5951 // an image loaded, make sure width and height are equal
5952 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5954 // if this is the first image to load successfully, allocate the cubemap memory
5955 if (!cubemappixels && image_width >= 1)
5957 cubemapsize = image_width;
5958 // note this clears to black, so unavailable sides are black
5959 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5961 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5963 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);
5966 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5968 Mem_Free(image_buffer);
5972 // if a cubemap loaded, upload it
5975 if (developer_loading.integer)
5976 Con_Printf("loading cubemap \"%s\"\n", basename);
5978 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5979 Mem_Free(cubemappixels);
5983 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5984 if (developer_loading.integer)
5986 Con_Printf("(tried tried images ");
5987 for (j = 0;j < 3;j++)
5988 for (i = 0;i < 6;i++)
5989 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5990 Con_Print(" and was unable to find any of them).\n");
5993 return cubemaptexture;
5996 rtexture_t *R_GetCubemap(const char *basename)
5999 for (i = 0;i < r_texture_numcubemaps;i++)
6000 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6001 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6002 if (i >= MAX_CUBEMAPS)
6003 return r_texture_whitecube;
6004 r_texture_numcubemaps++;
6005 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6006 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6007 return r_texture_cubemaps[i].texture;
6010 void R_FreeCubemaps(void)
6013 for (i = 0;i < r_texture_numcubemaps;i++)
6015 if (developer_loading.integer)
6016 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6017 if (r_texture_cubemaps[i].texture)
6018 R_FreeTexture(r_texture_cubemaps[i].texture);
6020 r_texture_numcubemaps = 0;
6023 void R_Main_FreeViewCache(void)
6025 if (r_refdef.viewcache.entityvisible)
6026 Mem_Free(r_refdef.viewcache.entityvisible);
6027 if (r_refdef.viewcache.world_pvsbits)
6028 Mem_Free(r_refdef.viewcache.world_pvsbits);
6029 if (r_refdef.viewcache.world_leafvisible)
6030 Mem_Free(r_refdef.viewcache.world_leafvisible);
6031 if (r_refdef.viewcache.world_surfacevisible)
6032 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6033 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6036 void R_Main_ResizeViewCache(void)
6038 int numentities = r_refdef.scene.numentities;
6039 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6040 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6041 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6042 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6043 if (r_refdef.viewcache.maxentities < numentities)
6045 r_refdef.viewcache.maxentities = numentities;
6046 if (r_refdef.viewcache.entityvisible)
6047 Mem_Free(r_refdef.viewcache.entityvisible);
6048 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6050 if (r_refdef.viewcache.world_numclusters != numclusters)
6052 r_refdef.viewcache.world_numclusters = numclusters;
6053 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6054 if (r_refdef.viewcache.world_pvsbits)
6055 Mem_Free(r_refdef.viewcache.world_pvsbits);
6056 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6058 if (r_refdef.viewcache.world_numleafs != numleafs)
6060 r_refdef.viewcache.world_numleafs = numleafs;
6061 if (r_refdef.viewcache.world_leafvisible)
6062 Mem_Free(r_refdef.viewcache.world_leafvisible);
6063 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6065 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6067 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6068 if (r_refdef.viewcache.world_surfacevisible)
6069 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6070 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6074 extern rtexture_t *loadingscreentexture;
6075 void gl_main_start(void)
6077 loadingscreentexture = NULL;
6078 r_texture_blanknormalmap = NULL;
6079 r_texture_white = NULL;
6080 r_texture_grey128 = NULL;
6081 r_texture_black = NULL;
6082 r_texture_whitecube = NULL;
6083 r_texture_normalizationcube = NULL;
6084 r_texture_fogattenuation = NULL;
6085 r_texture_gammaramps = NULL;
6086 r_texture_numcubemaps = 0;
6088 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6089 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6091 switch(vid.renderpath)
6093 case RENDERPATH_GL20:
6094 case RENDERPATH_CGGL:
6095 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6096 Cvar_SetValueQuick(&gl_combine, 1);
6097 Cvar_SetValueQuick(&r_glsl, 1);
6098 r_loadnormalmap = true;
6102 case RENDERPATH_GL13:
6103 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6104 Cvar_SetValueQuick(&gl_combine, 1);
6105 Cvar_SetValueQuick(&r_glsl, 0);
6106 r_loadnormalmap = false;
6107 r_loadgloss = false;
6110 case RENDERPATH_GL11:
6111 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6112 Cvar_SetValueQuick(&gl_combine, 0);
6113 Cvar_SetValueQuick(&r_glsl, 0);
6114 r_loadnormalmap = false;
6115 r_loadgloss = false;
6121 R_FrameData_Reset();
6125 memset(r_queries, 0, sizeof(r_queries));
6127 r_qwskincache = NULL;
6128 r_qwskincache_size = 0;
6130 // set up r_skinframe loading system for textures
6131 memset(&r_skinframe, 0, sizeof(r_skinframe));
6132 r_skinframe.loadsequence = 1;
6133 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6135 r_main_texturepool = R_AllocTexturePool();
6136 R_BuildBlankTextures();
6138 if (vid.support.arb_texture_cube_map)
6141 R_BuildNormalizationCube();
6143 r_texture_fogattenuation = NULL;
6144 r_texture_gammaramps = NULL;
6145 //r_texture_fogintensity = NULL;
6146 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6147 memset(&r_waterstate, 0, sizeof(r_waterstate));
6148 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6149 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6150 glslshaderstring = NULL;
6152 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6153 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6154 cgshaderstring = NULL;
6156 memset(&r_svbsp, 0, sizeof (r_svbsp));
6158 r_refdef.fogmasktable_density = 0;
6161 void gl_main_shutdown(void)
6164 R_FrameData_Reset();
6166 R_Main_FreeViewCache();
6169 qglDeleteQueriesARB(r_maxqueries, r_queries);
6173 memset(r_queries, 0, sizeof(r_queries));
6175 r_qwskincache = NULL;
6176 r_qwskincache_size = 0;
6178 // clear out the r_skinframe state
6179 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6180 memset(&r_skinframe, 0, sizeof(r_skinframe));
6183 Mem_Free(r_svbsp.nodes);
6184 memset(&r_svbsp, 0, sizeof (r_svbsp));
6185 R_FreeTexturePool(&r_main_texturepool);
6186 loadingscreentexture = NULL;
6187 r_texture_blanknormalmap = NULL;
6188 r_texture_white = NULL;
6189 r_texture_grey128 = NULL;
6190 r_texture_black = NULL;
6191 r_texture_whitecube = NULL;
6192 r_texture_normalizationcube = NULL;
6193 r_texture_fogattenuation = NULL;
6194 r_texture_gammaramps = NULL;
6195 r_texture_numcubemaps = 0;
6196 //r_texture_fogintensity = NULL;
6197 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6198 memset(&r_waterstate, 0, sizeof(r_waterstate));
6202 extern void CL_ParseEntityLump(char *entitystring);
6203 void gl_main_newmap(void)
6205 // FIXME: move this code to client
6207 char *entities, entname[MAX_QPATH];
6209 Mem_Free(r_qwskincache);
6210 r_qwskincache = NULL;
6211 r_qwskincache_size = 0;
6214 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6215 l = (int)strlen(entname) - 4;
6216 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6218 memcpy(entname + l, ".ent", 5);
6219 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6221 CL_ParseEntityLump(entities);
6226 if (cl.worldmodel->brush.entities)
6227 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6229 R_Main_FreeViewCache();
6231 R_FrameData_Reset();
6234 void GL_Main_Init(void)
6236 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6238 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6239 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6240 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6241 if (gamemode == GAME_NEHAHRA)
6243 Cvar_RegisterVariable (&gl_fogenable);
6244 Cvar_RegisterVariable (&gl_fogdensity);
6245 Cvar_RegisterVariable (&gl_fogred);
6246 Cvar_RegisterVariable (&gl_foggreen);
6247 Cvar_RegisterVariable (&gl_fogblue);
6248 Cvar_RegisterVariable (&gl_fogstart);
6249 Cvar_RegisterVariable (&gl_fogend);
6250 Cvar_RegisterVariable (&gl_skyclip);
6252 Cvar_RegisterVariable(&r_motionblur);
6253 Cvar_RegisterVariable(&r_motionblur_maxblur);
6254 Cvar_RegisterVariable(&r_motionblur_bmin);
6255 Cvar_RegisterVariable(&r_motionblur_vmin);
6256 Cvar_RegisterVariable(&r_motionblur_vmax);
6257 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6258 Cvar_RegisterVariable(&r_motionblur_randomize);
6259 Cvar_RegisterVariable(&r_damageblur);
6260 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6261 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6262 Cvar_RegisterVariable(&r_equalize_entities_by);
6263 Cvar_RegisterVariable(&r_equalize_entities_to);
6264 Cvar_RegisterVariable(&r_depthfirst);
6265 Cvar_RegisterVariable(&r_useinfinitefarclip);
6266 Cvar_RegisterVariable(&r_farclip_base);
6267 Cvar_RegisterVariable(&r_farclip_world);
6268 Cvar_RegisterVariable(&r_nearclip);
6269 Cvar_RegisterVariable(&r_showbboxes);
6270 Cvar_RegisterVariable(&r_showsurfaces);
6271 Cvar_RegisterVariable(&r_showtris);
6272 Cvar_RegisterVariable(&r_shownormals);
6273 Cvar_RegisterVariable(&r_showlighting);
6274 Cvar_RegisterVariable(&r_showshadowvolumes);
6275 Cvar_RegisterVariable(&r_showcollisionbrushes);
6276 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6277 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6278 Cvar_RegisterVariable(&r_showdisabledepthtest);
6279 Cvar_RegisterVariable(&r_drawportals);
6280 Cvar_RegisterVariable(&r_drawentities);
6281 Cvar_RegisterVariable(&r_cullentities_trace);
6282 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6283 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6284 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6285 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6286 Cvar_RegisterVariable(&r_drawviewmodel);
6287 Cvar_RegisterVariable(&r_speeds);
6288 Cvar_RegisterVariable(&r_fullbrights);
6289 Cvar_RegisterVariable(&r_wateralpha);
6290 Cvar_RegisterVariable(&r_dynamic);
6291 Cvar_RegisterVariable(&r_fullbright);
6292 Cvar_RegisterVariable(&r_shadows);
6293 Cvar_RegisterVariable(&r_shadows_darken);
6294 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6295 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6296 Cvar_RegisterVariable(&r_shadows_throwdistance);
6297 Cvar_RegisterVariable(&r_shadows_throwdirection);
6298 Cvar_RegisterVariable(&r_shadows_focus);
6299 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6300 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6301 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6302 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6303 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6304 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6305 Cvar_RegisterVariable(&r_fog_exp2);
6306 Cvar_RegisterVariable(&r_drawfog);
6307 Cvar_RegisterVariable(&r_transparentdepthmasking);
6308 Cvar_RegisterVariable(&r_texture_dds_load);
6309 Cvar_RegisterVariable(&r_texture_dds_save);
6310 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6311 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6312 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6313 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6314 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6315 Cvar_RegisterVariable(&r_textureunits);
6316 Cvar_RegisterVariable(&gl_combine);
6317 Cvar_RegisterVariable(&r_glsl);
6318 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6319 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6320 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6321 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6322 Cvar_RegisterVariable(&r_glsl_postprocess);
6323 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6324 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6325 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6326 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6327 Cvar_RegisterVariable(&r_water);
6328 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6329 Cvar_RegisterVariable(&r_water_clippingplanebias);
6330 Cvar_RegisterVariable(&r_water_refractdistort);
6331 Cvar_RegisterVariable(&r_water_reflectdistort);
6332 Cvar_RegisterVariable(&r_lerpsprites);
6333 Cvar_RegisterVariable(&r_lerpmodels);
6334 Cvar_RegisterVariable(&r_lerplightstyles);
6335 Cvar_RegisterVariable(&r_waterscroll);
6336 Cvar_RegisterVariable(&r_bloom);
6337 Cvar_RegisterVariable(&r_bloom_colorscale);
6338 Cvar_RegisterVariable(&r_bloom_brighten);
6339 Cvar_RegisterVariable(&r_bloom_blur);
6340 Cvar_RegisterVariable(&r_bloom_resolution);
6341 Cvar_RegisterVariable(&r_bloom_colorexponent);
6342 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6343 Cvar_RegisterVariable(&r_hdr);
6344 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6345 Cvar_RegisterVariable(&r_hdr_glowintensity);
6346 Cvar_RegisterVariable(&r_hdr_range);
6347 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6348 Cvar_RegisterVariable(&developer_texturelogging);
6349 Cvar_RegisterVariable(&gl_lightmaps);
6350 Cvar_RegisterVariable(&r_test);
6351 Cvar_RegisterVariable(&r_batchmode);
6352 Cvar_RegisterVariable(&r_glsl_saturation);
6353 Cvar_RegisterVariable(&r_framedatasize);
6354 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6355 Cvar_SetValue("r_fullbrights", 0);
6356 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6358 Cvar_RegisterVariable(&r_track_sprites);
6359 Cvar_RegisterVariable(&r_track_sprites_flags);
6360 Cvar_RegisterVariable(&r_track_sprites_scalew);
6361 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6362 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6363 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6366 extern void R_Textures_Init(void);
6367 extern void GL_Draw_Init(void);
6368 extern void GL_Main_Init(void);
6369 extern void R_Shadow_Init(void);
6370 extern void R_Sky_Init(void);
6371 extern void GL_Surf_Init(void);
6372 extern void R_Particles_Init(void);
6373 extern void R_Explosion_Init(void);
6374 extern void gl_backend_init(void);
6375 extern void Sbar_Init(void);
6376 extern void R_LightningBeams_Init(void);
6377 extern void Mod_RenderInit(void);
6378 extern void Font_Init(void);
6380 void Render_Init(void)
6393 R_LightningBeams_Init();
6402 extern char *ENGINE_EXTENSIONS;
6405 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6406 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6407 gl_version = (const char *)qglGetString(GL_VERSION);
6408 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6412 if (!gl_platformextensions)
6413 gl_platformextensions = "";
6415 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6416 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6417 Con_Printf("GL_VERSION: %s\n", gl_version);
6418 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6419 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6421 VID_CheckExtensions();
6423 // LordHavoc: report supported extensions
6424 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6426 // clear to black (loading plaque will be seen over this)
6428 qglClearColor(0,0,0,1);CHECKGLERROR
6429 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6432 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6436 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6438 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6441 p = r_refdef.view.frustum + i;
6446 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6450 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6454 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6458 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6462 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6466 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6470 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6474 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6482 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6486 for (i = 0;i < numplanes;i++)
6493 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6497 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6501 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6505 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6509 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6513 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6517 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6521 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6529 //==================================================================================
6531 // LordHavoc: this stores temporary data used within the same frame
6533 qboolean r_framedata_failed;
6534 static size_t r_framedata_size;
6535 static size_t r_framedata_current;
6536 static void *r_framedata_base;
6538 void R_FrameData_Reset(void)
6540 if (r_framedata_base)
6541 Mem_Free(r_framedata_base);
6542 r_framedata_base = NULL;
6543 r_framedata_size = 0;
6544 r_framedata_current = 0;
6545 r_framedata_failed = false;
6548 void R_FrameData_NewFrame(void)
6551 if (r_framedata_failed)
6552 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6553 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6554 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6555 if (r_framedata_size != wantedsize)
6557 r_framedata_size = wantedsize;
6558 if (r_framedata_base)
6559 Mem_Free(r_framedata_base);
6560 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6562 r_framedata_current = 0;
6563 r_framedata_failed = false;
6566 void *R_FrameData_Alloc(size_t size)
6570 // align to 16 byte boundary
6571 size = (size + 15) & ~15;
6572 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6573 r_framedata_current += size;
6576 if (r_framedata_current > r_framedata_size)
6577 r_framedata_failed = true;
6579 // return NULL on everything after a failure
6580 if (r_framedata_failed)
6586 void *R_FrameData_Store(size_t size, void *data)
6588 void *d = R_FrameData_Alloc(size);
6590 memcpy(d, data, size);
6594 //==================================================================================
6596 // LordHavoc: animcache originally written by Echon, rewritten since then
6599 * Animation cache prevents re-generating mesh data for an animated model
6600 * multiple times in one frame for lighting, shadowing, reflections, etc.
6603 void R_AnimCache_Free(void)
6607 void R_AnimCache_ClearCache(void)
6610 entity_render_t *ent;
6612 for (i = 0;i < r_refdef.scene.numentities;i++)
6614 ent = r_refdef.scene.entities[i];
6615 ent->animcache_vertex3f = NULL;
6616 ent->animcache_normal3f = NULL;
6617 ent->animcache_svector3f = NULL;
6618 ent->animcache_tvector3f = NULL;
6622 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6624 dp_model_t *model = ent->model;
6626 // see if it's already cached this frame
6627 if (ent->animcache_vertex3f)
6629 // add normals/tangents if needed
6630 if (wantnormals || wanttangents)
6632 if (ent->animcache_normal3f)
6633 wantnormals = false;
6634 if (ent->animcache_svector3f)
6635 wanttangents = false;
6636 if (wantnormals || wanttangents)
6638 numvertices = model->surfmesh.num_vertices;
6640 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6643 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6644 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6646 if (!r_framedata_failed)
6647 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6653 // see if this ent is worth caching
6654 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6656 // get some memory for this entity and generate mesh data
6657 numvertices = model->surfmesh.num_vertices;
6658 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6660 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6663 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6664 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6666 if (!r_framedata_failed)
6667 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6669 return !r_framedata_failed;
6672 void R_AnimCache_CacheVisibleEntities(void)
6675 qboolean wantnormals = !r_showsurfaces.integer;
6676 qboolean wanttangents = !r_showsurfaces.integer;
6678 switch(vid.renderpath)
6680 case RENDERPATH_GL20:
6681 case RENDERPATH_CGGL:
6683 case RENDERPATH_GL13:
6684 case RENDERPATH_GL11:
6685 wanttangents = false;
6689 // TODO: thread this
6690 // NOTE: R_PrepareRTLights() also caches entities
6692 for (i = 0;i < r_refdef.scene.numentities;i++)
6693 if (r_refdef.viewcache.entityvisible[i])
6694 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6697 //==================================================================================
6699 static void R_View_UpdateEntityLighting (void)
6702 entity_render_t *ent;
6703 vec3_t tempdiffusenormal, avg;
6704 vec_t f, fa, fd, fdd;
6705 qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6707 for (i = 0;i < r_refdef.scene.numentities;i++)
6709 ent = r_refdef.scene.entities[i];
6711 // skip unseen models
6712 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6716 if (ent->model && ent->model->brush.num_leafs)
6718 // TODO: use modellight for r_ambient settings on world?
6719 VectorSet(ent->modellight_ambient, 0, 0, 0);
6720 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6721 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6725 // fetch the lighting from the worldmodel data
6726 VectorClear(ent->modellight_ambient);
6727 VectorClear(ent->modellight_diffuse);
6728 VectorClear(tempdiffusenormal);
6729 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6732 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6733 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6734 if(ent->flags & RENDER_EQUALIZE)
6736 // first fix up ambient lighting...
6737 if(r_equalize_entities_minambient.value > 0)
6739 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6742 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6743 if(fa < r_equalize_entities_minambient.value * fd)
6746 // fa'/fd' = minambient
6747 // fa'+0.25*fd' = fa+0.25*fd
6749 // fa' = fd' * minambient
6750 // fd'*(0.25+minambient) = fa+0.25*fd
6752 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6753 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6755 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6756 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
6757 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6758 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6763 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6765 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6766 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6769 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6770 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6771 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6777 VectorSet(ent->modellight_ambient, 1, 1, 1);
6779 // move the light direction into modelspace coordinates for lighting code
6780 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6781 if(VectorLength2(ent->modellight_lightdir) == 0)
6782 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6783 VectorNormalize(ent->modellight_lightdir);
6787 #define MAX_LINEOFSIGHTTRACES 64
6789 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6792 vec3_t boxmins, boxmaxs;
6795 dp_model_t *model = r_refdef.scene.worldmodel;
6797 if (!model || !model->brush.TraceLineOfSight)
6800 // expand the box a little
6801 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6802 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6803 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6804 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6805 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6806 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6808 // return true if eye is inside enlarged box
6809 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6813 VectorCopy(eye, start);
6814 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6815 if (model->brush.TraceLineOfSight(model, start, end))
6818 // try various random positions
6819 for (i = 0;i < numsamples;i++)
6821 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6822 if (model->brush.TraceLineOfSight(model, start, end))
6830 static void R_View_UpdateEntityVisible (void)
6835 entity_render_t *ent;
6837 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6838 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6839 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
6840 : RENDER_EXTERIORMODEL;
6841 if (!r_drawviewmodel.integer)
6842 renderimask |= RENDER_VIEWMODEL;
6843 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6845 // worldmodel can check visibility
6846 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6847 for (i = 0;i < r_refdef.scene.numentities;i++)
6849 ent = r_refdef.scene.entities[i];
6850 if (!(ent->flags & renderimask))
6851 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)))
6852 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))
6853 r_refdef.viewcache.entityvisible[i] = true;
6855 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6857 for (i = 0;i < r_refdef.scene.numentities;i++)
6859 ent = r_refdef.scene.entities[i];
6860 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6862 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6864 continue; // temp entities do pvs only
6865 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6866 ent->last_trace_visibility = realtime;
6867 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6868 r_refdef.viewcache.entityvisible[i] = 0;
6875 // no worldmodel or it can't check visibility
6876 for (i = 0;i < r_refdef.scene.numentities;i++)
6878 ent = r_refdef.scene.entities[i];
6879 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));
6884 /// only used if skyrendermasked, and normally returns false
6885 int R_DrawBrushModelsSky (void)
6888 entity_render_t *ent;
6891 for (i = 0;i < r_refdef.scene.numentities;i++)
6893 if (!r_refdef.viewcache.entityvisible[i])
6895 ent = r_refdef.scene.entities[i];
6896 if (!ent->model || !ent->model->DrawSky)
6898 ent->model->DrawSky(ent);
6904 static void R_DrawNoModel(entity_render_t *ent);
6905 static void R_DrawModels(void)
6908 entity_render_t *ent;
6910 for (i = 0;i < r_refdef.scene.numentities;i++)
6912 if (!r_refdef.viewcache.entityvisible[i])
6914 ent = r_refdef.scene.entities[i];
6915 r_refdef.stats.entities++;
6916 if (ent->model && ent->model->Draw != NULL)
6917 ent->model->Draw(ent);
6923 static void R_DrawModelsDepth(void)
6926 entity_render_t *ent;
6928 for (i = 0;i < r_refdef.scene.numentities;i++)
6930 if (!r_refdef.viewcache.entityvisible[i])
6932 ent = r_refdef.scene.entities[i];
6933 if (ent->model && ent->model->DrawDepth != NULL)
6934 ent->model->DrawDepth(ent);
6938 static void R_DrawModelsDebug(void)
6941 entity_render_t *ent;
6943 for (i = 0;i < r_refdef.scene.numentities;i++)
6945 if (!r_refdef.viewcache.entityvisible[i])
6947 ent = r_refdef.scene.entities[i];
6948 if (ent->model && ent->model->DrawDebug != NULL)
6949 ent->model->DrawDebug(ent);
6953 static void R_DrawModelsAddWaterPlanes(void)
6956 entity_render_t *ent;
6958 for (i = 0;i < r_refdef.scene.numentities;i++)
6960 if (!r_refdef.viewcache.entityvisible[i])
6962 ent = r_refdef.scene.entities[i];
6963 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6964 ent->model->DrawAddWaterPlanes(ent);
6968 static void R_View_SetFrustum(void)
6971 double slopex, slopey;
6972 vec3_t forward, left, up, origin;
6974 // we can't trust r_refdef.view.forward and friends in reflected scenes
6975 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6978 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6979 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6980 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6981 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6982 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6983 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6984 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6985 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6986 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6987 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6988 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6989 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6993 zNear = r_refdef.nearclip;
6994 nudge = 1.0 - 1.0 / (1<<23);
6995 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6996 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6997 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6998 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6999 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7000 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7001 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7002 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7008 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7009 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7010 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7011 r_refdef.view.frustum[0].dist = m[15] - m[12];
7013 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7014 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7015 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7016 r_refdef.view.frustum[1].dist = m[15] + m[12];
7018 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7019 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7020 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7021 r_refdef.view.frustum[2].dist = m[15] - m[13];
7023 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7024 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7025 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7026 r_refdef.view.frustum[3].dist = m[15] + m[13];
7028 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7029 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7030 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7031 r_refdef.view.frustum[4].dist = m[15] - m[14];
7033 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7034 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7035 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7036 r_refdef.view.frustum[5].dist = m[15] + m[14];
7039 if (r_refdef.view.useperspective)
7041 slopex = 1.0 / r_refdef.view.frustum_x;
7042 slopey = 1.0 / r_refdef.view.frustum_y;
7043 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7044 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
7045 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
7046 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7047 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7049 // Leaving those out was a mistake, those were in the old code, and they
7050 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7051 // I couldn't reproduce it after adding those normalizations. --blub
7052 VectorNormalize(r_refdef.view.frustum[0].normal);
7053 VectorNormalize(r_refdef.view.frustum[1].normal);
7054 VectorNormalize(r_refdef.view.frustum[2].normal);
7055 VectorNormalize(r_refdef.view.frustum[3].normal);
7057 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7058 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]);
7059 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]);
7060 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]);
7061 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]);
7063 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7064 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7065 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7066 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7067 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7071 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7072 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7073 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7074 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7075 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7076 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7077 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7078 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7079 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7080 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7082 r_refdef.view.numfrustumplanes = 5;
7084 if (r_refdef.view.useclipplane)
7086 r_refdef.view.numfrustumplanes = 6;
7087 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7090 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7091 PlaneClassify(r_refdef.view.frustum + i);
7093 // LordHavoc: note to all quake engine coders, Quake had a special case
7094 // for 90 degrees which assumed a square view (wrong), so I removed it,
7095 // Quake2 has it disabled as well.
7097 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7098 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7099 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7100 //PlaneClassify(&frustum[0]);
7102 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7103 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7104 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7105 //PlaneClassify(&frustum[1]);
7107 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7108 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7109 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7110 //PlaneClassify(&frustum[2]);
7112 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7113 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7114 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7115 //PlaneClassify(&frustum[3]);
7118 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7119 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7120 //PlaneClassify(&frustum[4]);
7123 void R_View_Update(void)
7125 R_Main_ResizeViewCache();
7126 R_View_SetFrustum();
7127 R_View_WorldVisibility(r_refdef.view.useclipplane);
7128 R_View_UpdateEntityVisible();
7129 R_View_UpdateEntityLighting();
7132 void R_SetupView(qboolean allowwaterclippingplane)
7134 const float *customclipplane = NULL;
7136 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7138 // LordHavoc: couldn't figure out how to make this approach the
7139 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7140 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7141 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7142 dist = r_refdef.view.clipplane.dist;
7143 plane[0] = r_refdef.view.clipplane.normal[0];
7144 plane[1] = r_refdef.view.clipplane.normal[1];
7145 plane[2] = r_refdef.view.clipplane.normal[2];
7147 customclipplane = plane;
7150 if (!r_refdef.view.useperspective)
7151 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);
7152 else if (vid.stencil && r_useinfinitefarclip.integer)
7153 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);
7155 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);
7156 R_SetViewport(&r_refdef.view.viewport);
7159 void R_EntityMatrix(const matrix4x4_t *matrix)
7161 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7163 gl_modelmatrixchanged = false;
7164 gl_modelmatrix = *matrix;
7165 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7166 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7167 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7168 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7170 switch(vid.renderpath)
7172 case RENDERPATH_GL20:
7173 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7174 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7175 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7177 case RENDERPATH_CGGL:
7180 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7181 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7182 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7185 case RENDERPATH_GL13:
7186 case RENDERPATH_GL11:
7187 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7193 void R_ResetViewRendering2D(void)
7195 r_viewport_t viewport;
7198 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7199 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);
7200 R_SetViewport(&viewport);
7201 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7202 GL_Color(1, 1, 1, 1);
7203 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7204 GL_BlendFunc(GL_ONE, GL_ZERO);
7205 GL_AlphaTest(false);
7206 GL_ScissorTest(false);
7207 GL_DepthMask(false);
7208 GL_DepthRange(0, 1);
7209 GL_DepthTest(false);
7210 R_EntityMatrix(&identitymatrix);
7211 R_Mesh_ResetTextureState();
7212 GL_PolygonOffset(0, 0);
7213 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7214 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7215 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7216 qglStencilMask(~0);CHECKGLERROR
7217 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7218 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7219 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7222 void R_ResetViewRendering3D(void)
7227 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7228 GL_Color(1, 1, 1, 1);
7229 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7230 GL_BlendFunc(GL_ONE, GL_ZERO);
7231 GL_AlphaTest(false);
7232 GL_ScissorTest(true);
7234 GL_DepthRange(0, 1);
7236 R_EntityMatrix(&identitymatrix);
7237 R_Mesh_ResetTextureState();
7238 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7239 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7240 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7241 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7242 qglStencilMask(~0);CHECKGLERROR
7243 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7244 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7245 GL_CullFace(r_refdef.view.cullface_back);
7248 void R_RenderScene(void);
7249 void R_RenderWaterPlanes(void);
7251 static void R_Water_StartFrame(void)
7254 int waterwidth, waterheight, texturewidth, textureheight;
7255 r_waterstate_waterplane_t *p;
7257 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7260 switch(vid.renderpath)
7262 case RENDERPATH_GL20:
7263 case RENDERPATH_CGGL:
7265 case RENDERPATH_GL13:
7266 case RENDERPATH_GL11:
7270 // set waterwidth and waterheight to the water resolution that will be
7271 // used (often less than the screen resolution for faster rendering)
7272 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7273 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7275 // calculate desired texture sizes
7276 // can't use water if the card does not support the texture size
7277 if (!r_water.integer || r_showsurfaces.integer)
7278 texturewidth = textureheight = waterwidth = waterheight = 0;
7279 else if (vid.support.arb_texture_non_power_of_two)
7281 texturewidth = waterwidth;
7282 textureheight = waterheight;
7286 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7287 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7290 // allocate textures as needed
7291 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7293 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7294 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7296 if (p->texture_refraction)
7297 R_FreeTexture(p->texture_refraction);
7298 p->texture_refraction = NULL;
7299 if (p->texture_reflection)
7300 R_FreeTexture(p->texture_reflection);
7301 p->texture_reflection = NULL;
7303 memset(&r_waterstate, 0, sizeof(r_waterstate));
7304 r_waterstate.texturewidth = texturewidth;
7305 r_waterstate.textureheight = textureheight;
7308 if (r_waterstate.texturewidth)
7310 r_waterstate.enabled = true;
7312 // when doing a reduced render (HDR) we want to use a smaller area
7313 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7314 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7316 // set up variables that will be used in shader setup
7317 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7318 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7319 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7320 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7323 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7324 r_waterstate.numwaterplanes = 0;
7327 void R_Water_AddWaterPlane(msurface_t *surface)
7329 int triangleindex, planeindex;
7335 r_waterstate_waterplane_t *p;
7336 texture_t *t = R_GetCurrentTexture(surface->texture);
7337 // just use the first triangle with a valid normal for any decisions
7338 VectorClear(normal);
7339 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7341 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7342 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7343 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7344 TriangleNormal(vert[0], vert[1], vert[2], normal);
7345 if (VectorLength2(normal) >= 0.001)
7349 VectorCopy(normal, plane.normal);
7350 VectorNormalize(plane.normal);
7351 plane.dist = DotProduct(vert[0], plane.normal);
7352 PlaneClassify(&plane);
7353 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7355 // skip backfaces (except if nocullface is set)
7356 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7358 VectorNegate(plane.normal, plane.normal);
7360 PlaneClassify(&plane);
7364 // find a matching plane if there is one
7365 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7366 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7368 if (planeindex >= r_waterstate.maxwaterplanes)
7369 return; // nothing we can do, out of planes
7371 // if this triangle does not fit any known plane rendered this frame, add one
7372 if (planeindex >= r_waterstate.numwaterplanes)
7374 // store the new plane
7375 r_waterstate.numwaterplanes++;
7377 // clear materialflags and pvs
7378 p->materialflags = 0;
7379 p->pvsvalid = false;
7381 // merge this surface's materialflags into the waterplane
7382 p->materialflags |= t->currentmaterialflags;
7383 // merge this surface's PVS into the waterplane
7384 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7385 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7386 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7388 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7393 static void R_Water_ProcessPlanes(void)
7395 r_refdef_view_t originalview;
7396 r_refdef_view_t myview;
7398 r_waterstate_waterplane_t *p;
7400 originalview = r_refdef.view;
7402 // make sure enough textures are allocated
7403 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7405 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7407 if (!p->texture_refraction)
7408 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);
7409 if (!p->texture_refraction)
7413 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7415 if (!p->texture_reflection)
7416 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);
7417 if (!p->texture_reflection)
7423 r_refdef.view = originalview;
7424 r_refdef.view.showdebug = false;
7425 r_refdef.view.width = r_waterstate.waterwidth;
7426 r_refdef.view.height = r_waterstate.waterheight;
7427 r_refdef.view.useclipplane = true;
7428 myview = r_refdef.view;
7429 r_waterstate.renderingscene = true;
7430 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7432 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7434 r_refdef.view = myview;
7435 // render reflected scene and copy into texture
7436 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7437 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7438 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7439 r_refdef.view.clipplane = p->plane;
7440 // reverse the cullface settings for this render
7441 r_refdef.view.cullface_front = GL_FRONT;
7442 r_refdef.view.cullface_back = GL_BACK;
7443 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7445 r_refdef.view.usecustompvs = true;
7447 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7449 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7452 R_ResetViewRendering3D();
7453 R_ClearScreen(r_refdef.fogenabled);
7457 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);
7460 // render the normal view scene and copy into texture
7461 // (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)
7462 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7464 r_waterstate.renderingrefraction = true;
7465 r_refdef.view = myview;
7466 r_refdef.view.clipplane = p->plane;
7467 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7468 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7469 PlaneClassify(&r_refdef.view.clipplane);
7471 R_ResetViewRendering3D();
7472 R_ClearScreen(r_refdef.fogenabled);
7476 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);
7477 r_waterstate.renderingrefraction = false;
7481 r_waterstate.renderingscene = false;
7482 r_refdef.view = originalview;
7483 R_ResetViewRendering3D();
7484 R_ClearScreen(r_refdef.fogenabled);
7488 r_refdef.view = originalview;
7489 r_waterstate.renderingscene = false;
7490 Cvar_SetValueQuick(&r_water, 0);
7491 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7495 void R_Bloom_StartFrame(void)
7497 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7499 switch(vid.renderpath)
7501 case RENDERPATH_GL20:
7502 case RENDERPATH_CGGL:
7504 case RENDERPATH_GL13:
7505 case RENDERPATH_GL11:
7509 // set bloomwidth and bloomheight to the bloom resolution that will be
7510 // used (often less than the screen resolution for faster rendering)
7511 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7512 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7513 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7514 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7515 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7517 // calculate desired texture sizes
7518 if (vid.support.arb_texture_non_power_of_two)
7520 screentexturewidth = r_refdef.view.width;
7521 screentextureheight = r_refdef.view.height;
7522 bloomtexturewidth = r_bloomstate.bloomwidth;
7523 bloomtextureheight = r_bloomstate.bloomheight;
7527 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7528 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7529 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7530 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7533 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))
7535 Cvar_SetValueQuick(&r_hdr, 0);
7536 Cvar_SetValueQuick(&r_bloom, 0);
7537 Cvar_SetValueQuick(&r_motionblur, 0);
7538 Cvar_SetValueQuick(&r_damageblur, 0);
7541 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)))
7542 screentexturewidth = screentextureheight = 0;
7543 if (!r_hdr.integer && !r_bloom.integer)
7544 bloomtexturewidth = bloomtextureheight = 0;
7546 // allocate textures as needed
7547 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7549 if (r_bloomstate.texture_screen)
7550 R_FreeTexture(r_bloomstate.texture_screen);
7551 r_bloomstate.texture_screen = NULL;
7552 r_bloomstate.screentexturewidth = screentexturewidth;
7553 r_bloomstate.screentextureheight = screentextureheight;
7554 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7555 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7557 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7559 if (r_bloomstate.texture_bloom)
7560 R_FreeTexture(r_bloomstate.texture_bloom);
7561 r_bloomstate.texture_bloom = NULL;
7562 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7563 r_bloomstate.bloomtextureheight = bloomtextureheight;
7564 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7565 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7568 // when doing a reduced render (HDR) we want to use a smaller area
7569 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7570 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7571 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7572 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7573 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7575 // set up a texcoord array for the full resolution screen image
7576 // (we have to keep this around to copy back during final render)
7577 r_bloomstate.screentexcoord2f[0] = 0;
7578 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7579 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7580 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7581 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7582 r_bloomstate.screentexcoord2f[5] = 0;
7583 r_bloomstate.screentexcoord2f[6] = 0;
7584 r_bloomstate.screentexcoord2f[7] = 0;
7586 // set up a texcoord array for the reduced resolution bloom image
7587 // (which will be additive blended over the screen image)
7588 r_bloomstate.bloomtexcoord2f[0] = 0;
7589 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7590 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7591 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7592 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7593 r_bloomstate.bloomtexcoord2f[5] = 0;
7594 r_bloomstate.bloomtexcoord2f[6] = 0;
7595 r_bloomstate.bloomtexcoord2f[7] = 0;
7597 if (r_hdr.integer || r_bloom.integer)
7599 r_bloomstate.enabled = true;
7600 r_bloomstate.hdr = r_hdr.integer != 0;
7603 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);
7606 void R_Bloom_CopyBloomTexture(float colorscale)
7608 r_refdef.stats.bloom++;
7610 // scale down screen texture to the bloom texture size
7612 R_SetViewport(&r_bloomstate.viewport);
7613 GL_BlendFunc(GL_ONE, GL_ZERO);
7614 GL_Color(colorscale, colorscale, colorscale, 1);
7615 // TODO: optimize with multitexture or GLSL
7616 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7617 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7618 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7619 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7621 // we now have a bloom image in the framebuffer
7622 // copy it into the bloom image texture for later processing
7623 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);
7624 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7627 void R_Bloom_CopyHDRTexture(void)
7629 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);
7630 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7633 void R_Bloom_MakeTexture(void)
7636 float xoffset, yoffset, r, brighten;
7638 r_refdef.stats.bloom++;
7640 R_ResetViewRendering2D();
7641 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7642 R_Mesh_ColorPointer(NULL, 0, 0);
7644 // we have a bloom image in the framebuffer
7646 R_SetViewport(&r_bloomstate.viewport);
7648 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7651 r = bound(0, r_bloom_colorexponent.value / x, 1);
7652 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7653 GL_Color(r, r, r, 1);
7654 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7655 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
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 // copy the vertically blurred bloom view to a texture
7660 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);
7661 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7664 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7665 brighten = r_bloom_brighten.value;
7667 brighten *= r_hdr_range.value;
7668 brighten = sqrt(brighten);
7670 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7671 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7672 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7674 for (dir = 0;dir < 2;dir++)
7676 // blend on at multiple vertical offsets to achieve a vertical blur
7677 // TODO: do offset blends using GLSL
7678 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7679 GL_BlendFunc(GL_ONE, GL_ZERO);
7680 for (x = -range;x <= range;x++)
7682 if (!dir){xoffset = 0;yoffset = x;}
7683 else {xoffset = x;yoffset = 0;}
7684 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7685 yoffset /= (float)r_bloomstate.bloomtextureheight;
7686 // compute a texcoord array with the specified x and y offset
7687 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7688 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7689 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7690 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7691 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7692 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7693 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7694 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7695 // this r value looks like a 'dot' particle, fading sharply to
7696 // black at the edges
7697 // (probably not realistic but looks good enough)
7698 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7699 //r = brighten/(range*2+1);
7700 r = brighten / (range * 2 + 1);
7702 r *= (1 - x*x/(float)(range*range));
7703 GL_Color(r, r, r, 1);
7704 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7705 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7706 GL_BlendFunc(GL_ONE, GL_ONE);
7709 // copy the vertically blurred bloom view to a texture
7710 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);
7711 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7714 // apply subtract last
7715 // (just like it would be in a GLSL shader)
7716 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7718 GL_BlendFunc(GL_ONE, GL_ZERO);
7719 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7720 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7721 GL_Color(1, 1, 1, 1);
7722 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7723 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7725 GL_BlendFunc(GL_ONE, GL_ONE);
7726 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7727 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7728 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7729 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7730 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7731 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7732 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7734 // copy the darkened bloom view to a texture
7735 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);
7736 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7740 void R_HDR_RenderBloomTexture(void)
7742 int oldwidth, oldheight;
7743 float oldcolorscale;
7745 oldcolorscale = r_refdef.view.colorscale;
7746 oldwidth = r_refdef.view.width;
7747 oldheight = r_refdef.view.height;
7748 r_refdef.view.width = r_bloomstate.bloomwidth;
7749 r_refdef.view.height = r_bloomstate.bloomheight;
7751 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7752 // TODO: add exposure compensation features
7753 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7755 r_refdef.view.showdebug = false;
7756 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7758 R_ResetViewRendering3D();
7760 R_ClearScreen(r_refdef.fogenabled);
7761 if (r_timereport_active)
7762 R_TimeReport("HDRclear");
7765 if (r_timereport_active)
7766 R_TimeReport("visibility");
7768 // only do secondary renders with HDR if r_hdr is 2 or higher
7769 r_waterstate.numwaterplanes = 0;
7770 if (r_waterstate.enabled && r_hdr.integer >= 2)
7771 R_RenderWaterPlanes();
7773 r_refdef.view.showdebug = true;
7775 r_waterstate.numwaterplanes = 0;
7777 R_ResetViewRendering2D();
7779 R_Bloom_CopyHDRTexture();
7780 R_Bloom_MakeTexture();
7782 // restore the view settings
7783 r_refdef.view.width = oldwidth;
7784 r_refdef.view.height = oldheight;
7785 r_refdef.view.colorscale = oldcolorscale;
7787 R_ResetViewRendering3D();
7789 R_ClearScreen(r_refdef.fogenabled);
7790 if (r_timereport_active)
7791 R_TimeReport("viewclear");
7794 static void R_BlendView(void)
7796 unsigned int permutation;
7797 float uservecs[4][4];
7799 switch (vid.renderpath)
7801 case RENDERPATH_GL20:
7802 case RENDERPATH_CGGL:
7804 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7805 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7806 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7807 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7808 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7810 if (r_bloomstate.texture_screen)
7812 // make sure the buffer is available
7813 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7815 R_ResetViewRendering2D();
7816 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7817 R_Mesh_ColorPointer(NULL, 0, 0);
7819 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7821 // declare variables
7823 static float avgspeed;
7825 speed = VectorLength(cl.movement_velocity);
7827 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7828 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7830 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7831 speed = bound(0, speed, 1);
7832 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7834 // calculate values into a standard alpha
7835 cl.motionbluralpha = 1 - exp(-
7837 (r_motionblur.value * speed / 80)
7839 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7842 max(0.0001, cl.time - cl.oldtime) // fps independent
7845 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7846 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7848 if (cl.motionbluralpha > 0)
7850 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7851 GL_Color(1, 1, 1, cl.motionbluralpha);
7852 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7853 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7854 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7855 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7859 // copy view into the screen texture
7860 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);
7861 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7863 else if (!r_bloomstate.texture_bloom)
7865 // we may still have to do view tint...
7866 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7868 // apply a color tint to the whole view
7869 R_ResetViewRendering2D();
7870 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7871 R_Mesh_ColorPointer(NULL, 0, 0);
7872 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7873 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7874 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7875 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7877 break; // no screen processing, no bloom, skip it
7880 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7882 // render simple bloom effect
7883 // copy the screen and shrink it and darken it for the bloom process
7884 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7885 // make the bloom texture
7886 R_Bloom_MakeTexture();
7889 #if _MSC_VER >= 1400
7890 #define sscanf sscanf_s
7892 memset(uservecs, 0, sizeof(uservecs));
7893 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7894 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7895 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7896 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7898 R_ResetViewRendering2D();
7899 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7900 R_Mesh_ColorPointer(NULL, 0, 0);
7901 GL_Color(1, 1, 1, 1);
7902 GL_BlendFunc(GL_ONE, GL_ZERO);
7903 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7904 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7906 switch(vid.renderpath)
7908 case RENDERPATH_GL20:
7909 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7910 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7911 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7912 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7913 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]);
7914 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7915 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]);
7916 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]);
7917 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]);
7918 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]);
7919 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7920 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7922 case RENDERPATH_CGGL:
7924 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7925 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7926 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7927 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7928 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
7929 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7930 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
7931 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
7932 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
7933 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
7934 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7935 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7941 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7942 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7944 case RENDERPATH_GL13:
7945 case RENDERPATH_GL11:
7946 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7948 // apply a color tint to the whole view
7949 R_ResetViewRendering2D();
7950 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7951 R_Mesh_ColorPointer(NULL, 0, 0);
7952 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7953 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7954 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7955 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7961 matrix4x4_t r_waterscrollmatrix;
7963 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7965 if (r_refdef.fog_density)
7967 r_refdef.fogcolor[0] = r_refdef.fog_red;
7968 r_refdef.fogcolor[1] = r_refdef.fog_green;
7969 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7971 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7972 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7973 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7974 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7978 VectorCopy(r_refdef.fogcolor, fogvec);
7979 // color.rgb *= ContrastBoost * SceneBrightness;
7980 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7981 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7982 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7983 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7988 void R_UpdateVariables(void)
7992 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7994 r_refdef.farclip = r_farclip_base.value;
7995 if (r_refdef.scene.worldmodel)
7996 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7997 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7999 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8000 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8001 r_refdef.polygonfactor = 0;
8002 r_refdef.polygonoffset = 0;
8003 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8004 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8006 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8007 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8008 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8009 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8010 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8011 if (r_showsurfaces.integer)
8013 r_refdef.scene.rtworld = false;
8014 r_refdef.scene.rtworldshadows = false;
8015 r_refdef.scene.rtdlight = false;
8016 r_refdef.scene.rtdlightshadows = false;
8017 r_refdef.lightmapintensity = 0;
8020 if (gamemode == GAME_NEHAHRA)
8022 if (gl_fogenable.integer)
8024 r_refdef.oldgl_fogenable = true;
8025 r_refdef.fog_density = gl_fogdensity.value;
8026 r_refdef.fog_red = gl_fogred.value;
8027 r_refdef.fog_green = gl_foggreen.value;
8028 r_refdef.fog_blue = gl_fogblue.value;
8029 r_refdef.fog_alpha = 1;
8030 r_refdef.fog_start = 0;
8031 r_refdef.fog_end = gl_skyclip.value;
8032 r_refdef.fog_height = 1<<30;
8033 r_refdef.fog_fadedepth = 128;
8035 else if (r_refdef.oldgl_fogenable)
8037 r_refdef.oldgl_fogenable = false;
8038 r_refdef.fog_density = 0;
8039 r_refdef.fog_red = 0;
8040 r_refdef.fog_green = 0;
8041 r_refdef.fog_blue = 0;
8042 r_refdef.fog_alpha = 0;
8043 r_refdef.fog_start = 0;
8044 r_refdef.fog_end = 0;
8045 r_refdef.fog_height = 1<<30;
8046 r_refdef.fog_fadedepth = 128;
8050 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8051 r_refdef.fog_start = max(0, r_refdef.fog_start);
8052 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8054 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8056 if (r_refdef.fog_density && r_drawfog.integer)
8058 r_refdef.fogenabled = true;
8059 // this is the point where the fog reaches 0.9986 alpha, which we
8060 // consider a good enough cutoff point for the texture
8061 // (0.9986 * 256 == 255.6)
8062 if (r_fog_exp2.integer)
8063 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8065 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8066 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8067 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8068 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8069 // fog color was already set
8070 // update the fog texture
8071 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)
8072 R_BuildFogTexture();
8075 r_refdef.fogenabled = false;
8077 switch(vid.renderpath)
8079 case RENDERPATH_GL20:
8080 case RENDERPATH_CGGL:
8081 if(v_glslgamma.integer && !vid_gammatables_trivial)
8083 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8085 // build GLSL gamma texture
8086 #define RAMPWIDTH 256
8087 unsigned short ramp[RAMPWIDTH * 3];
8088 unsigned char rampbgr[RAMPWIDTH][4];
8091 r_texture_gammaramps_serial = vid_gammatables_serial;
8093 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8094 for(i = 0; i < RAMPWIDTH; ++i)
8096 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8097 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8098 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8101 if (r_texture_gammaramps)
8103 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8107 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);
8113 // remove GLSL gamma texture
8116 case RENDERPATH_GL13:
8117 case RENDERPATH_GL11:
8122 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8123 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8129 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8130 if( scenetype != r_currentscenetype ) {
8131 // store the old scenetype
8132 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8133 r_currentscenetype = scenetype;
8134 // move in the new scene
8135 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8144 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8146 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8147 if( scenetype == r_currentscenetype ) {
8148 return &r_refdef.scene;
8150 return &r_scenes_store[ scenetype ];
8159 void R_RenderView(void)
8161 if (r_timereport_active)
8162 R_TimeReport("start");
8163 r_textureframe++; // used only by R_GetCurrentTexture
8164 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8166 if (!r_drawentities.integer)
8167 r_refdef.scene.numentities = 0;
8169 R_AnimCache_ClearCache();
8170 R_FrameData_NewFrame();
8172 if (r_refdef.view.isoverlay)
8174 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8175 GL_Clear( GL_DEPTH_BUFFER_BIT );
8176 R_TimeReport("depthclear");
8178 r_refdef.view.showdebug = false;
8180 r_waterstate.enabled = false;
8181 r_waterstate.numwaterplanes = 0;
8189 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8190 return; //Host_Error ("R_RenderView: NULL worldmodel");
8192 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8194 // break apart the view matrix into vectors for various purposes
8195 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8196 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8197 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8198 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8199 // make an inverted copy of the view matrix for tracking sprites
8200 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8202 R_Shadow_UpdateWorldLightSelection();
8204 R_Bloom_StartFrame();
8205 R_Water_StartFrame();
8208 if (r_timereport_active)
8209 R_TimeReport("viewsetup");
8211 R_ResetViewRendering3D();
8213 if (r_refdef.view.clear || r_refdef.fogenabled)
8215 R_ClearScreen(r_refdef.fogenabled);
8216 if (r_timereport_active)
8217 R_TimeReport("viewclear");
8219 r_refdef.view.clear = true;
8221 // this produces a bloom texture to be used in R_BlendView() later
8222 if (r_hdr.integer && r_bloomstate.bloomwidth)
8224 R_HDR_RenderBloomTexture();
8225 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8226 r_textureframe++; // used only by R_GetCurrentTexture
8229 r_refdef.view.showdebug = true;
8232 if (r_timereport_active)
8233 R_TimeReport("visibility");
8235 r_waterstate.numwaterplanes = 0;
8236 if (r_waterstate.enabled)
8237 R_RenderWaterPlanes();
8240 r_waterstate.numwaterplanes = 0;
8243 if (r_timereport_active)
8244 R_TimeReport("blendview");
8246 GL_Scissor(0, 0, vid.width, vid.height);
8247 GL_ScissorTest(false);
8251 void R_RenderWaterPlanes(void)
8253 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8255 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8256 if (r_timereport_active)
8257 R_TimeReport("waterworld");
8260 // don't let sound skip if going slow
8261 if (r_refdef.scene.extraupdate)
8264 R_DrawModelsAddWaterPlanes();
8265 if (r_timereport_active)
8266 R_TimeReport("watermodels");
8268 if (r_waterstate.numwaterplanes)
8270 R_Water_ProcessPlanes();
8271 if (r_timereport_active)
8272 R_TimeReport("waterscenes");
8276 extern void R_DrawLightningBeams (void);
8277 extern void VM_CL_AddPolygonsToMeshQueue (void);
8278 extern void R_DrawPortals (void);
8279 extern cvar_t cl_locs_show;
8280 static void R_DrawLocs(void);
8281 static void R_DrawEntityBBoxes(void);
8282 static void R_DrawModelDecals(void);
8283 extern void R_DrawModelShadows(void);
8284 extern void R_DrawModelShadowMaps(void);
8285 extern cvar_t cl_decals_newsystem;
8286 extern qboolean r_shadow_usingdeferredprepass;
8287 void R_RenderScene(void)
8289 qboolean shadowmapping = false;
8291 r_refdef.stats.renders++;
8295 // don't let sound skip if going slow
8296 if (r_refdef.scene.extraupdate)
8299 R_MeshQueue_BeginScene();
8303 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);
8305 if (cl.csqc_vidvars.drawworld)
8307 // don't let sound skip if going slow
8308 if (r_refdef.scene.extraupdate)
8311 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8313 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8314 if (r_timereport_active)
8315 R_TimeReport("worldsky");
8318 if (R_DrawBrushModelsSky() && r_timereport_active)
8319 R_TimeReport("bmodelsky");
8321 if (skyrendermasked && skyrenderlater)
8323 // we have to force off the water clipping plane while rendering sky
8327 if (r_timereport_active)
8328 R_TimeReport("sky");
8332 R_AnimCache_CacheVisibleEntities();
8333 if (r_timereport_active)
8334 R_TimeReport("animation");
8336 R_Shadow_PrepareLights();
8337 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8338 R_Shadow_PrepareModelShadows();
8339 if (r_timereport_active)
8340 R_TimeReport("preparelights");
8342 if (R_Shadow_ShadowMappingEnabled())
8343 shadowmapping = true;
8345 if (r_shadow_usingdeferredprepass)
8346 R_Shadow_DrawPrepass();
8348 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8350 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8351 if (r_timereport_active)
8352 R_TimeReport("worlddepth");
8354 if (r_depthfirst.integer >= 2)
8356 R_DrawModelsDepth();
8357 if (r_timereport_active)
8358 R_TimeReport("modeldepth");
8361 if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8363 R_DrawModelShadowMaps();
8364 R_ResetViewRendering3D();
8365 // don't let sound skip if going slow
8366 if (r_refdef.scene.extraupdate)
8370 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8372 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8373 if (r_timereport_active)
8374 R_TimeReport("world");
8377 // don't let sound skip if going slow
8378 if (r_refdef.scene.extraupdate)
8382 if (r_timereport_active)
8383 R_TimeReport("models");
8385 // don't let sound skip if going slow
8386 if (r_refdef.scene.extraupdate)
8389 if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8391 R_DrawModelShadows();
8392 R_ResetViewRendering3D();
8393 // don't let sound skip if going slow
8394 if (r_refdef.scene.extraupdate)
8398 if (!r_shadow_usingdeferredprepass)
8400 R_Shadow_DrawLights();
8401 if (r_timereport_active)
8402 R_TimeReport("rtlights");
8405 // don't let sound skip if going slow
8406 if (r_refdef.scene.extraupdate)
8409 if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8411 R_DrawModelShadows();
8412 R_ResetViewRendering3D();
8413 // don't let sound skip if going slow
8414 if (r_refdef.scene.extraupdate)
8418 if (cl.csqc_vidvars.drawworld)
8420 if (cl_decals_newsystem.integer)
8422 R_DrawModelDecals();
8423 if (r_timereport_active)
8424 R_TimeReport("modeldecals");
8429 if (r_timereport_active)
8430 R_TimeReport("decals");
8434 if (r_timereport_active)
8435 R_TimeReport("particles");
8438 if (r_timereport_active)
8439 R_TimeReport("explosions");
8441 R_DrawLightningBeams();
8442 if (r_timereport_active)
8443 R_TimeReport("lightning");
8446 VM_CL_AddPolygonsToMeshQueue();
8448 if (r_refdef.view.showdebug)
8450 if (cl_locs_show.integer)
8453 if (r_timereport_active)
8454 R_TimeReport("showlocs");
8457 if (r_drawportals.integer)
8460 if (r_timereport_active)
8461 R_TimeReport("portals");
8464 if (r_showbboxes.value > 0)
8466 R_DrawEntityBBoxes();
8467 if (r_timereport_active)
8468 R_TimeReport("bboxes");
8472 R_MeshQueue_RenderTransparent();
8473 if (r_timereport_active)
8474 R_TimeReport("drawtrans");
8476 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))
8478 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8479 if (r_timereport_active)
8480 R_TimeReport("worlddebug");
8481 R_DrawModelsDebug();
8482 if (r_timereport_active)
8483 R_TimeReport("modeldebug");
8486 if (cl.csqc_vidvars.drawworld)
8488 R_Shadow_DrawCoronas();
8489 if (r_timereport_active)
8490 R_TimeReport("coronas");
8493 // don't let sound skip if going slow
8494 if (r_refdef.scene.extraupdate)
8497 R_ResetViewRendering2D();
8500 static const unsigned short bboxelements[36] =
8510 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8513 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8515 RSurf_ActiveWorldEntity();
8517 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8518 GL_DepthMask(false);
8519 GL_DepthRange(0, 1);
8520 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8521 R_Mesh_ResetTextureState();
8523 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8524 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8525 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8526 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8527 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8528 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8529 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8530 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8531 R_FillColors(color4f, 8, cr, cg, cb, ca);
8532 if (r_refdef.fogenabled)
8534 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8536 f1 = RSurf_FogVertex(v);
8538 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8539 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8540 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8543 R_Mesh_VertexPointer(vertex3f, 0, 0);
8544 R_Mesh_ColorPointer(color4f, 0, 0);
8545 R_Mesh_ResetTextureState();
8546 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8547 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8550 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8554 prvm_edict_t *edict;
8555 prvm_prog_t *prog_save = prog;
8557 // this function draws bounding boxes of server entities
8561 GL_CullFace(GL_NONE);
8562 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8566 for (i = 0;i < numsurfaces;i++)
8568 edict = PRVM_EDICT_NUM(surfacelist[i]);
8569 switch ((int)edict->fields.server->solid)
8571 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8572 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8573 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8574 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8575 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8576 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8578 color[3] *= r_showbboxes.value;
8579 color[3] = bound(0, color[3], 1);
8580 GL_DepthTest(!r_showdisabledepthtest.integer);
8581 GL_CullFace(r_refdef.view.cullface_front);
8582 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8588 static void R_DrawEntityBBoxes(void)
8591 prvm_edict_t *edict;
8593 prvm_prog_t *prog_save = prog;
8595 // this function draws bounding boxes of server entities
8601 for (i = 0;i < prog->num_edicts;i++)
8603 edict = PRVM_EDICT_NUM(i);
8604 if (edict->priv.server->free)
8606 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8607 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8609 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8611 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8612 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8618 static const int nomodelelement3i[24] =
8630 static const unsigned short nomodelelement3s[24] =
8642 static const float nomodelvertex3f[6*3] =
8652 static const float nomodelcolor4f[6*4] =
8654 0.0f, 0.0f, 0.5f, 1.0f,
8655 0.0f, 0.0f, 0.5f, 1.0f,
8656 0.0f, 0.5f, 0.0f, 1.0f,
8657 0.0f, 0.5f, 0.0f, 1.0f,
8658 0.5f, 0.0f, 0.0f, 1.0f,
8659 0.5f, 0.0f, 0.0f, 1.0f
8662 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8668 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);
8670 // this is only called once per entity so numsurfaces is always 1, and
8671 // surfacelist is always {0}, so this code does not handle batches
8673 if (rsurface.ent_flags & RENDER_ADDITIVE)
8675 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8676 GL_DepthMask(false);
8678 else if (rsurface.colormod[3] < 1)
8680 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8681 GL_DepthMask(false);
8685 GL_BlendFunc(GL_ONE, GL_ZERO);
8688 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8689 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8690 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8691 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8692 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8693 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8694 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8695 R_Mesh_ColorPointer(color4f, 0, 0);
8696 for (i = 0, c = color4f;i < 6;i++, c += 4)
8698 c[0] *= rsurface.colormod[0];
8699 c[1] *= rsurface.colormod[1];
8700 c[2] *= rsurface.colormod[2];
8701 c[3] *= rsurface.colormod[3];
8703 if (r_refdef.fogenabled)
8705 for (i = 0, c = color4f;i < 6;i++, c += 4)
8707 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8709 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8710 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8711 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8714 R_Mesh_ResetTextureState();
8715 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8718 void R_DrawNoModel(entity_render_t *ent)
8721 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8722 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8723 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8725 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8728 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8730 vec3_t right1, right2, diff, normal;
8732 VectorSubtract (org2, org1, normal);
8734 // calculate 'right' vector for start
8735 VectorSubtract (r_refdef.view.origin, org1, diff);
8736 CrossProduct (normal, diff, right1);
8737 VectorNormalize (right1);
8739 // calculate 'right' vector for end
8740 VectorSubtract (r_refdef.view.origin, org2, diff);
8741 CrossProduct (normal, diff, right2);
8742 VectorNormalize (right2);
8744 vert[ 0] = org1[0] + width * right1[0];
8745 vert[ 1] = org1[1] + width * right1[1];
8746 vert[ 2] = org1[2] + width * right1[2];
8747 vert[ 3] = org1[0] - width * right1[0];
8748 vert[ 4] = org1[1] - width * right1[1];
8749 vert[ 5] = org1[2] - width * right1[2];
8750 vert[ 6] = org2[0] - width * right2[0];
8751 vert[ 7] = org2[1] - width * right2[1];
8752 vert[ 8] = org2[2] - width * right2[2];
8753 vert[ 9] = org2[0] + width * right2[0];
8754 vert[10] = org2[1] + width * right2[1];
8755 vert[11] = org2[2] + width * right2[2];
8758 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)
8760 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8761 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8762 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8763 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8764 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8765 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8766 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8767 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8768 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8769 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8770 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8771 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8774 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8779 VectorSet(v, x, y, z);
8780 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8781 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8783 if (i == mesh->numvertices)
8785 if (mesh->numvertices < mesh->maxvertices)
8787 VectorCopy(v, vertex3f);
8788 mesh->numvertices++;
8790 return mesh->numvertices;
8796 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8800 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8801 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8802 e = mesh->element3i + mesh->numtriangles * 3;
8803 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8805 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8806 if (mesh->numtriangles < mesh->maxtriangles)
8811 mesh->numtriangles++;
8813 element[1] = element[2];
8817 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8821 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8822 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8823 e = mesh->element3i + mesh->numtriangles * 3;
8824 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8826 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8827 if (mesh->numtriangles < mesh->maxtriangles)
8832 mesh->numtriangles++;
8834 element[1] = element[2];
8838 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8839 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8841 int planenum, planenum2;
8844 mplane_t *plane, *plane2;
8846 double temppoints[2][256*3];
8847 // figure out how large a bounding box we need to properly compute this brush
8849 for (w = 0;w < numplanes;w++)
8850 maxdist = max(maxdist, fabs(planes[w].dist));
8851 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8852 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8853 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8857 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8858 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8860 if (planenum2 == planenum)
8862 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);
8865 if (tempnumpoints < 3)
8867 // generate elements forming a triangle fan for this polygon
8868 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8872 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)
8874 texturelayer_t *layer;
8875 layer = t->currentlayers + t->currentnumlayers++;
8877 layer->depthmask = depthmask;
8878 layer->blendfunc1 = blendfunc1;
8879 layer->blendfunc2 = blendfunc2;
8880 layer->texture = texture;
8881 layer->texmatrix = *matrix;
8882 layer->color[0] = r;
8883 layer->color[1] = g;
8884 layer->color[2] = b;
8885 layer->color[3] = a;
8888 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8891 index = parms[2] + r_refdef.scene.time * parms[3];
8892 index -= floor(index);
8896 case Q3WAVEFUNC_NONE:
8897 case Q3WAVEFUNC_NOISE:
8898 case Q3WAVEFUNC_COUNT:
8901 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8902 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8903 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8904 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8905 case Q3WAVEFUNC_TRIANGLE:
8907 f = index - floor(index);
8918 return (float)(parms[0] + parms[1] * f);
8921 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8926 matrix4x4_t matrix, temp;
8927 switch(tcmod->tcmod)
8931 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8932 matrix = r_waterscrollmatrix;
8934 matrix = identitymatrix;
8936 case Q3TCMOD_ENTITYTRANSLATE:
8937 // this is used in Q3 to allow the gamecode to control texcoord
8938 // scrolling on the entity, which is not supported in darkplaces yet.
8939 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8941 case Q3TCMOD_ROTATE:
8942 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8943 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8944 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8947 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8949 case Q3TCMOD_SCROLL:
8950 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8952 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8953 w = (int) tcmod->parms[0];
8954 h = (int) tcmod->parms[1];
8955 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8957 idx = (int) floor(f * w * h);
8958 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8960 case Q3TCMOD_STRETCH:
8961 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8962 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8964 case Q3TCMOD_TRANSFORM:
8965 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8966 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8967 VectorSet(tcmat + 6, 0 , 0 , 1);
8968 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8969 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8971 case Q3TCMOD_TURBULENT:
8972 // this is handled in the RSurf_PrepareVertices function
8973 matrix = identitymatrix;
8977 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8980 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8982 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8983 char name[MAX_QPATH];
8984 skinframe_t *skinframe;
8985 unsigned char pixels[296*194];
8986 strlcpy(cache->name, skinname, sizeof(cache->name));
8987 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8988 if (developer_loading.integer)
8989 Con_Printf("loading %s\n", name);
8990 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8991 if (!skinframe || !skinframe->base)
8994 fs_offset_t filesize;
8996 f = FS_LoadFile(name, tempmempool, true, &filesize);
8999 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9000 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9004 cache->skinframe = skinframe;
9007 texture_t *R_GetCurrentTexture(texture_t *t)
9010 const entity_render_t *ent = rsurface.entity;
9011 dp_model_t *model = ent->model;
9012 q3shaderinfo_layer_tcmod_t *tcmod;
9014 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9015 return t->currentframe;
9016 t->update_lastrenderframe = r_textureframe;
9017 t->update_lastrenderentity = (void *)ent;
9019 // switch to an alternate material if this is a q1bsp animated material
9021 texture_t *texture = t;
9022 int s = rsurface.ent_skinnum;
9023 if ((unsigned int)s >= (unsigned int)model->numskins)
9025 if (model->skinscenes)
9027 if (model->skinscenes[s].framecount > 1)
9028 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9030 s = model->skinscenes[s].firstframe;
9033 t = t + s * model->num_surfaces;
9036 // use an alternate animation if the entity's frame is not 0,
9037 // and only if the texture has an alternate animation
9038 if (rsurface.ent_alttextures && t->anim_total[1])
9039 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9041 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9043 texture->currentframe = t;
9046 // update currentskinframe to be a qw skin or animation frame
9047 if (rsurface.ent_qwskin >= 0)
9049 i = rsurface.ent_qwskin;
9050 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9052 r_qwskincache_size = cl.maxclients;
9054 Mem_Free(r_qwskincache);
9055 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9057 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9058 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9059 t->currentskinframe = r_qwskincache[i].skinframe;
9060 if (t->currentskinframe == NULL)
9061 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9063 else if (t->numskinframes >= 2)
9064 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9065 if (t->backgroundnumskinframes >= 2)
9066 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9068 t->currentmaterialflags = t->basematerialflags;
9069 t->currentalpha = rsurface.colormod[3];
9070 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9071 t->currentalpha *= r_wateralpha.value;
9072 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9073 t->currentalpha *= t->r_water_wateralpha;
9074 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9075 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9076 if (!(rsurface.ent_flags & RENDER_LIGHT))
9077 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9078 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9080 // pick a model lighting mode
9081 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9082 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9084 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9086 if (rsurface.ent_flags & RENDER_ADDITIVE)
9087 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9088 else if (t->currentalpha < 1)
9089 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9090 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9091 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9092 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9093 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9094 if (t->backgroundnumskinframes)
9095 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9096 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9098 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9099 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9102 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9103 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9104 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9106 // there is no tcmod
9107 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9109 t->currenttexmatrix = r_waterscrollmatrix;
9110 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9112 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9114 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9115 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9118 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9119 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9120 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9121 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9123 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9124 if (t->currentskinframe->qpixels)
9125 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9126 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9127 if (!t->basetexture)
9128 t->basetexture = r_texture_notexture;
9129 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9130 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9131 t->nmaptexture = t->currentskinframe->nmap;
9132 if (!t->nmaptexture)
9133 t->nmaptexture = r_texture_blanknormalmap;
9134 t->glosstexture = r_texture_black;
9135 t->glowtexture = t->currentskinframe->glow;
9136 t->fogtexture = t->currentskinframe->fog;
9137 t->reflectmasktexture = t->currentskinframe->reflect;
9138 if (t->backgroundnumskinframes)
9140 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9141 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9142 t->backgroundglosstexture = r_texture_black;
9143 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9144 if (!t->backgroundnmaptexture)
9145 t->backgroundnmaptexture = r_texture_blanknormalmap;
9149 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9150 t->backgroundnmaptexture = r_texture_blanknormalmap;
9151 t->backgroundglosstexture = r_texture_black;
9152 t->backgroundglowtexture = NULL;
9154 t->specularpower = r_shadow_glossexponent.value;
9155 // TODO: store reference values for these in the texture?
9156 t->specularscale = 0;
9157 if (r_shadow_gloss.integer > 0)
9159 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9161 if (r_shadow_glossintensity.value > 0)
9163 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9164 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9165 t->specularscale = r_shadow_glossintensity.value;
9168 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9170 t->glosstexture = r_texture_white;
9171 t->backgroundglosstexture = r_texture_white;
9172 t->specularscale = r_shadow_gloss2intensity.value;
9173 t->specularpower = r_shadow_gloss2exponent.value;
9176 t->specularscale *= t->specularscalemod;
9177 t->specularpower *= t->specularpowermod;
9179 // lightmaps mode looks bad with dlights using actual texturing, so turn
9180 // off the colormap and glossmap, but leave the normalmap on as it still
9181 // accurately represents the shading involved
9182 if (gl_lightmaps.integer)
9184 t->basetexture = r_texture_grey128;
9185 t->pantstexture = r_texture_black;
9186 t->shirttexture = r_texture_black;
9187 t->nmaptexture = r_texture_blanknormalmap;
9188 t->glosstexture = r_texture_black;
9189 t->glowtexture = NULL;
9190 t->fogtexture = NULL;
9191 t->reflectmasktexture = NULL;
9192 t->backgroundbasetexture = NULL;
9193 t->backgroundnmaptexture = r_texture_blanknormalmap;
9194 t->backgroundglosstexture = r_texture_black;
9195 t->backgroundglowtexture = NULL;
9196 t->specularscale = 0;
9197 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9200 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9201 VectorClear(t->dlightcolor);
9202 t->currentnumlayers = 0;
9203 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9205 int blendfunc1, blendfunc2;
9207 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9209 blendfunc1 = GL_SRC_ALPHA;
9210 blendfunc2 = GL_ONE;
9212 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9214 blendfunc1 = GL_SRC_ALPHA;
9215 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9217 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9219 blendfunc1 = t->customblendfunc[0];
9220 blendfunc2 = t->customblendfunc[1];
9224 blendfunc1 = GL_ONE;
9225 blendfunc2 = GL_ZERO;
9227 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9228 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9230 // fullbright is not affected by r_refdef.lightmapintensity
9231 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]);
9232 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9233 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]);
9234 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9235 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]);
9239 vec3_t ambientcolor;
9241 // set the color tint used for lights affecting this surface
9242 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9244 // q3bsp has no lightmap updates, so the lightstylevalue that
9245 // would normally be baked into the lightmap must be
9246 // applied to the color
9247 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9248 if (model->type == mod_brushq3)
9249 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9250 colorscale *= r_refdef.lightmapintensity;
9251 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9252 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9253 // basic lit geometry
9254 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]);
9255 // add pants/shirt if needed
9256 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9257 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]);
9258 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9259 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]);
9260 // now add ambient passes if needed
9261 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9263 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]);
9264 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9265 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]);
9266 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9267 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]);
9270 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9271 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]);
9272 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9274 // if this is opaque use alpha blend which will darken the earlier
9277 // if this is an alpha blended material, all the earlier passes
9278 // were darkened by fog already, so we only need to add the fog
9279 // color ontop through the fog mask texture
9281 // if this is an additive blended material, all the earlier passes
9282 // were darkened by fog already, and we should not add fog color
9283 // (because the background was not darkened, there is no fog color
9284 // that was lost behind it).
9285 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]);
9289 return t->currentframe;
9292 rsurfacestate_t rsurface;
9294 void R_Mesh_ResizeArrays(int newvertices)
9297 if (rsurface.array_size >= newvertices)
9299 if (rsurface.array_modelvertex3f)
9300 Mem_Free(rsurface.array_modelvertex3f);
9301 rsurface.array_size = (newvertices + 1023) & ~1023;
9302 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9303 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9304 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9305 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9306 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9307 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9308 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9309 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9310 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9311 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9312 rsurface.array_color4f = base + rsurface.array_size * 27;
9313 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9316 void RSurf_ActiveWorldEntity(void)
9318 dp_model_t *model = r_refdef.scene.worldmodel;
9319 //if (rsurface.entity == r_refdef.scene.worldentity)
9321 rsurface.entity = r_refdef.scene.worldentity;
9322 rsurface.skeleton = NULL;
9323 rsurface.ent_skinnum = 0;
9324 rsurface.ent_qwskin = -1;
9325 rsurface.ent_shadertime = 0;
9326 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9327 if (rsurface.array_size < model->surfmesh.num_vertices)
9328 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9329 rsurface.matrix = identitymatrix;
9330 rsurface.inversematrix = identitymatrix;
9331 rsurface.matrixscale = 1;
9332 rsurface.inversematrixscale = 1;
9333 R_EntityMatrix(&identitymatrix);
9334 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9335 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9336 rsurface.fograngerecip = r_refdef.fograngerecip;
9337 rsurface.fogheightfade = r_refdef.fogheightfade;
9338 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9339 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9340 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9341 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9342 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9343 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9344 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9345 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9346 rsurface.colormod[3] = 1;
9347 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);
9348 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9349 rsurface.frameblend[0].lerp = 1;
9350 rsurface.ent_alttextures = false;
9351 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9352 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9353 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9354 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9355 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9356 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9357 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9358 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9359 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9360 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9361 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9362 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9363 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9364 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9365 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9366 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9367 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9368 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9369 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9370 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9371 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9372 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9373 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9374 rsurface.modelelement3i = model->surfmesh.data_element3i;
9375 rsurface.modelelement3s = model->surfmesh.data_element3s;
9376 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9377 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9378 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9379 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9380 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9381 rsurface.modelsurfaces = model->data_surfaces;
9382 rsurface.generatedvertex = false;
9383 rsurface.vertex3f = rsurface.modelvertex3f;
9384 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9385 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9386 rsurface.svector3f = rsurface.modelsvector3f;
9387 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9388 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9389 rsurface.tvector3f = rsurface.modeltvector3f;
9390 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9391 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9392 rsurface.normal3f = rsurface.modelnormal3f;
9393 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9394 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9395 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9398 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9400 dp_model_t *model = ent->model;
9401 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9403 rsurface.entity = (entity_render_t *)ent;
9404 rsurface.skeleton = ent->skeleton;
9405 rsurface.ent_skinnum = ent->skinnum;
9406 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;
9407 rsurface.ent_shadertime = ent->shadertime;
9408 rsurface.ent_flags = ent->flags;
9409 if (rsurface.array_size < model->surfmesh.num_vertices)
9410 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9411 rsurface.matrix = ent->matrix;
9412 rsurface.inversematrix = ent->inversematrix;
9413 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9414 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9415 R_EntityMatrix(&rsurface.matrix);
9416 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9417 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9418 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9419 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9420 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9421 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9422 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9423 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9424 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9425 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9426 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9427 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9428 rsurface.colormod[3] = ent->alpha;
9429 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9430 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9431 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9432 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9433 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9434 if (ent->model->brush.submodel && !prepass)
9436 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9437 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9439 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9441 if (ent->animcache_vertex3f && !r_framedata_failed)
9443 rsurface.modelvertex3f = ent->animcache_vertex3f;
9444 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9445 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9446 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9448 else if (wanttangents)
9450 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9451 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9452 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9453 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9454 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9456 else if (wantnormals)
9458 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9459 rsurface.modelsvector3f = NULL;
9460 rsurface.modeltvector3f = NULL;
9461 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9462 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9466 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9467 rsurface.modelsvector3f = NULL;
9468 rsurface.modeltvector3f = NULL;
9469 rsurface.modelnormal3f = NULL;
9470 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9472 rsurface.modelvertex3f_bufferobject = 0;
9473 rsurface.modelvertex3f_bufferoffset = 0;
9474 rsurface.modelsvector3f_bufferobject = 0;
9475 rsurface.modelsvector3f_bufferoffset = 0;
9476 rsurface.modeltvector3f_bufferobject = 0;
9477 rsurface.modeltvector3f_bufferoffset = 0;
9478 rsurface.modelnormal3f_bufferobject = 0;
9479 rsurface.modelnormal3f_bufferoffset = 0;
9480 rsurface.generatedvertex = true;
9484 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9485 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9486 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9487 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9488 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9489 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9490 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9491 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9492 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9493 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9494 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9495 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9496 rsurface.generatedvertex = false;
9498 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9499 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9500 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9501 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9502 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9503 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9504 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9505 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9506 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9507 rsurface.modelelement3i = model->surfmesh.data_element3i;
9508 rsurface.modelelement3s = model->surfmesh.data_element3s;
9509 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9510 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9511 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9512 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9513 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9514 rsurface.modelsurfaces = model->data_surfaces;
9515 rsurface.vertex3f = rsurface.modelvertex3f;
9516 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9517 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9518 rsurface.svector3f = rsurface.modelsvector3f;
9519 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9520 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9521 rsurface.tvector3f = rsurface.modeltvector3f;
9522 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9523 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9524 rsurface.normal3f = rsurface.modelnormal3f;
9525 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9526 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9527 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9530 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)
9532 rsurface.entity = r_refdef.scene.worldentity;
9533 rsurface.skeleton = NULL;
9534 rsurface.ent_skinnum = 0;
9535 rsurface.ent_qwskin = -1;
9536 rsurface.ent_shadertime = shadertime;
9537 rsurface.ent_flags = entflags;
9538 rsurface.modelnum_vertices = numvertices;
9539 rsurface.modelnum_triangles = numtriangles;
9540 if (rsurface.array_size < rsurface.modelnum_vertices)
9541 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9542 rsurface.matrix = *matrix;
9543 rsurface.inversematrix = *inversematrix;
9544 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9545 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9546 R_EntityMatrix(&rsurface.matrix);
9547 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9548 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9549 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9550 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9551 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9552 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9553 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9554 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9555 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9556 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9557 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9558 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9559 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);
9560 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9561 rsurface.frameblend[0].lerp = 1;
9562 rsurface.ent_alttextures = false;
9563 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9564 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9567 rsurface.modelvertex3f = vertex3f;
9568 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9569 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9570 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9572 else if (wantnormals)
9574 rsurface.modelvertex3f = vertex3f;
9575 rsurface.modelsvector3f = NULL;
9576 rsurface.modeltvector3f = NULL;
9577 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9581 rsurface.modelvertex3f = vertex3f;
9582 rsurface.modelsvector3f = NULL;
9583 rsurface.modeltvector3f = NULL;
9584 rsurface.modelnormal3f = NULL;
9586 rsurface.modelvertex3f_bufferobject = 0;
9587 rsurface.modelvertex3f_bufferoffset = 0;
9588 rsurface.modelsvector3f_bufferobject = 0;
9589 rsurface.modelsvector3f_bufferoffset = 0;
9590 rsurface.modeltvector3f_bufferobject = 0;
9591 rsurface.modeltvector3f_bufferoffset = 0;
9592 rsurface.modelnormal3f_bufferobject = 0;
9593 rsurface.modelnormal3f_bufferoffset = 0;
9594 rsurface.generatedvertex = true;
9595 rsurface.modellightmapcolor4f = color4f;
9596 rsurface.modellightmapcolor4f_bufferobject = 0;
9597 rsurface.modellightmapcolor4f_bufferoffset = 0;
9598 rsurface.modeltexcoordtexture2f = texcoord2f;
9599 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9600 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9601 rsurface.modeltexcoordlightmap2f = NULL;
9602 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9603 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9604 rsurface.modelelement3i = element3i;
9605 rsurface.modelelement3s = element3s;
9606 rsurface.modelelement3i_bufferobject = 0;
9607 rsurface.modelelement3s_bufferobject = 0;
9608 rsurface.modellightmapoffsets = NULL;
9609 rsurface.modelsurfaces = NULL;
9610 rsurface.vertex3f = rsurface.modelvertex3f;
9611 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9612 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9613 rsurface.svector3f = rsurface.modelsvector3f;
9614 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9615 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9616 rsurface.tvector3f = rsurface.modeltvector3f;
9617 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9618 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9619 rsurface.normal3f = rsurface.modelnormal3f;
9620 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9621 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9622 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9624 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9626 if ((wantnormals || wanttangents) && !normal3f)
9627 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9628 if (wanttangents && !svector3f)
9629 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);
9633 float RSurf_FogPoint(const float *v)
9635 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9636 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9637 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9638 float FogHeightFade = r_refdef.fogheightfade;
9640 unsigned int fogmasktableindex;
9641 if (r_refdef.fogplaneviewabove)
9642 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9644 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9645 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9646 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9649 float RSurf_FogVertex(const float *v)
9651 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9652 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9653 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9654 float FogHeightFade = rsurface.fogheightfade;
9656 unsigned int fogmasktableindex;
9657 if (r_refdef.fogplaneviewabove)
9658 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9660 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9661 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9662 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9665 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9666 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9669 int texturesurfaceindex;
9674 const float *v1, *in_tc;
9676 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9678 q3shaderinfo_deform_t *deform;
9679 // 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
9680 if (rsurface.generatedvertex)
9682 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9683 generatenormals = true;
9684 for (i = 0;i < Q3MAXDEFORMS;i++)
9686 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9688 generatetangents = true;
9689 generatenormals = true;
9691 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9692 generatenormals = true;
9694 if (generatenormals && !rsurface.modelnormal3f)
9696 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9697 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9698 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9699 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9701 if (generatetangents && !rsurface.modelsvector3f)
9703 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9704 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9705 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9706 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9707 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9708 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9709 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);
9712 rsurface.vertex3f = rsurface.modelvertex3f;
9713 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9714 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9715 rsurface.svector3f = rsurface.modelsvector3f;
9716 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9717 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9718 rsurface.tvector3f = rsurface.modeltvector3f;
9719 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9720 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9721 rsurface.normal3f = rsurface.modelnormal3f;
9722 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9723 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9724 // if vertices are deformed (sprite flares and things in maps, possibly
9725 // water waves, bulges and other deformations), generate them into
9726 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9727 // (may be static model data or generated data for an animated model, or
9728 // the previous deform pass)
9729 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9731 switch (deform->deform)
9734 case Q3DEFORM_PROJECTIONSHADOW:
9735 case Q3DEFORM_TEXT0:
9736 case Q3DEFORM_TEXT1:
9737 case Q3DEFORM_TEXT2:
9738 case Q3DEFORM_TEXT3:
9739 case Q3DEFORM_TEXT4:
9740 case Q3DEFORM_TEXT5:
9741 case Q3DEFORM_TEXT6:
9742 case Q3DEFORM_TEXT7:
9745 case Q3DEFORM_AUTOSPRITE:
9746 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9747 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9748 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9749 VectorNormalize(newforward);
9750 VectorNormalize(newright);
9751 VectorNormalize(newup);
9752 // make deformed versions of only the model vertices used by the specified surfaces
9753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9755 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9756 // a single autosprite surface can contain multiple sprites...
9757 for (j = 0;j < surface->num_vertices - 3;j += 4)
9759 VectorClear(center);
9760 for (i = 0;i < 4;i++)
9761 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9762 VectorScale(center, 0.25f, center);
9763 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9764 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9765 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9766 for (i = 0;i < 4;i++)
9768 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9769 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9772 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);
9773 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);
9775 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9776 rsurface.vertex3f_bufferobject = 0;
9777 rsurface.vertex3f_bufferoffset = 0;
9778 rsurface.svector3f = rsurface.array_deformedsvector3f;
9779 rsurface.svector3f_bufferobject = 0;
9780 rsurface.svector3f_bufferoffset = 0;
9781 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9782 rsurface.tvector3f_bufferobject = 0;
9783 rsurface.tvector3f_bufferoffset = 0;
9784 rsurface.normal3f = rsurface.array_deformednormal3f;
9785 rsurface.normal3f_bufferobject = 0;
9786 rsurface.normal3f_bufferoffset = 0;
9788 case Q3DEFORM_AUTOSPRITE2:
9789 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9790 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9791 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9792 VectorNormalize(newforward);
9793 VectorNormalize(newright);
9794 VectorNormalize(newup);
9795 // make deformed versions of only the model vertices used by the specified surfaces
9796 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9798 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9799 const float *v1, *v2;
9809 memset(shortest, 0, sizeof(shortest));
9810 // a single autosprite surface can contain multiple sprites...
9811 for (j = 0;j < surface->num_vertices - 3;j += 4)
9813 VectorClear(center);
9814 for (i = 0;i < 4;i++)
9815 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9816 VectorScale(center, 0.25f, center);
9817 // find the two shortest edges, then use them to define the
9818 // axis vectors for rotating around the central axis
9819 for (i = 0;i < 6;i++)
9821 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9822 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9824 Debug_PolygonBegin(NULL, 0);
9825 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9826 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);
9827 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9830 l = VectorDistance2(v1, v2);
9831 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9833 l += (1.0f / 1024.0f);
9834 if (shortest[0].length2 > l || i == 0)
9836 shortest[1] = shortest[0];
9837 shortest[0].length2 = l;
9838 shortest[0].v1 = v1;
9839 shortest[0].v2 = v2;
9841 else if (shortest[1].length2 > l || i == 1)
9843 shortest[1].length2 = l;
9844 shortest[1].v1 = v1;
9845 shortest[1].v2 = v2;
9848 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9849 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9851 Debug_PolygonBegin(NULL, 0);
9852 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9853 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);
9854 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9857 // this calculates the right vector from the shortest edge
9858 // and the up vector from the edge midpoints
9859 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9860 VectorNormalize(right);
9861 VectorSubtract(end, start, up);
9862 VectorNormalize(up);
9863 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9864 VectorSubtract(rsurface.localvieworigin, center, forward);
9865 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9866 VectorNegate(forward, forward);
9867 VectorReflect(forward, 0, up, forward);
9868 VectorNormalize(forward);
9869 CrossProduct(up, forward, newright);
9870 VectorNormalize(newright);
9872 Debug_PolygonBegin(NULL, 0);
9873 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);
9874 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9875 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9879 Debug_PolygonBegin(NULL, 0);
9880 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9881 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9882 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9885 // rotate the quad around the up axis vector, this is made
9886 // especially easy by the fact we know the quad is flat,
9887 // so we only have to subtract the center position and
9888 // measure distance along the right vector, and then
9889 // multiply that by the newright vector and add back the
9891 // we also need to subtract the old position to undo the
9892 // displacement from the center, which we do with a
9893 // DotProduct, the subtraction/addition of center is also
9894 // optimized into DotProducts here
9895 l = DotProduct(right, center);
9896 for (i = 0;i < 4;i++)
9898 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9899 f = DotProduct(right, v1) - l;
9900 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9903 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);
9904 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);
9906 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9907 rsurface.vertex3f_bufferobject = 0;
9908 rsurface.vertex3f_bufferoffset = 0;
9909 rsurface.svector3f = rsurface.array_deformedsvector3f;
9910 rsurface.svector3f_bufferobject = 0;
9911 rsurface.svector3f_bufferoffset = 0;
9912 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9913 rsurface.tvector3f_bufferobject = 0;
9914 rsurface.tvector3f_bufferoffset = 0;
9915 rsurface.normal3f = rsurface.array_deformednormal3f;
9916 rsurface.normal3f_bufferobject = 0;
9917 rsurface.normal3f_bufferoffset = 0;
9919 case Q3DEFORM_NORMAL:
9920 // deform the normals to make reflections wavey
9921 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9923 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9924 for (j = 0;j < surface->num_vertices;j++)
9927 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9928 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9929 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9930 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9931 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9932 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9933 VectorNormalize(normal);
9935 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);
9937 rsurface.svector3f = rsurface.array_deformedsvector3f;
9938 rsurface.svector3f_bufferobject = 0;
9939 rsurface.svector3f_bufferoffset = 0;
9940 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9941 rsurface.tvector3f_bufferobject = 0;
9942 rsurface.tvector3f_bufferoffset = 0;
9943 rsurface.normal3f = rsurface.array_deformednormal3f;
9944 rsurface.normal3f_bufferobject = 0;
9945 rsurface.normal3f_bufferoffset = 0;
9948 // deform vertex array to make wavey water and flags and such
9949 waveparms[0] = deform->waveparms[0];
9950 waveparms[1] = deform->waveparms[1];
9951 waveparms[2] = deform->waveparms[2];
9952 waveparms[3] = deform->waveparms[3];
9953 // this is how a divisor of vertex influence on deformation
9954 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9955 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9956 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9958 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9959 for (j = 0;j < surface->num_vertices;j++)
9961 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9962 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9963 // if the wavefunc depends on time, evaluate it per-vertex
9966 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9967 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9969 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9972 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9973 rsurface.vertex3f_bufferobject = 0;
9974 rsurface.vertex3f_bufferoffset = 0;
9976 case Q3DEFORM_BULGE:
9977 // deform vertex array to make the surface have moving bulges
9978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9980 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9981 for (j = 0;j < surface->num_vertices;j++)
9983 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9984 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9987 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9988 rsurface.vertex3f_bufferobject = 0;
9989 rsurface.vertex3f_bufferoffset = 0;
9992 // deform vertex array
9993 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9994 VectorScale(deform->parms, scale, waveparms);
9995 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9997 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9998 for (j = 0;j < surface->num_vertices;j++)
9999 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10001 rsurface.vertex3f = rsurface.array_deformedvertex3f;
10002 rsurface.vertex3f_bufferobject = 0;
10003 rsurface.vertex3f_bufferoffset = 0;
10007 // generate texcoords based on the chosen texcoord source
10008 switch(rsurface.texture->tcgen.tcgen)
10011 case Q3TCGEN_TEXTURE:
10012 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10013 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
10014 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
10016 case Q3TCGEN_LIGHTMAP:
10017 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
10018 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10019 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10021 case Q3TCGEN_VECTOR:
10022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10024 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10025 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)
10027 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10028 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10031 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10032 rsurface.texcoordtexture2f_bufferobject = 0;
10033 rsurface.texcoordtexture2f_bufferoffset = 0;
10035 case Q3TCGEN_ENVIRONMENT:
10036 // make environment reflections using a spheremap
10037 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10039 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10040 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10041 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10042 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10043 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10045 // identical to Q3A's method, but executed in worldspace so
10046 // carried models can be shiny too
10048 float viewer[3], d, reflected[3], worldreflected[3];
10050 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10051 // VectorNormalize(viewer);
10053 d = DotProduct(normal, viewer);
10055 reflected[0] = normal[0]*2*d - viewer[0];
10056 reflected[1] = normal[1]*2*d - viewer[1];
10057 reflected[2] = normal[2]*2*d - viewer[2];
10058 // note: this is proportinal to viewer, so we can normalize later
10060 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10061 VectorNormalize(worldreflected);
10063 // note: this sphere map only uses world x and z!
10064 // so positive and negative y will LOOK THE SAME.
10065 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10066 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10069 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10070 rsurface.texcoordtexture2f_bufferobject = 0;
10071 rsurface.texcoordtexture2f_bufferoffset = 0;
10074 // the only tcmod that needs software vertex processing is turbulent, so
10075 // check for it here and apply the changes if needed
10076 // and we only support that as the first one
10077 // (handling a mixture of turbulent and other tcmods would be problematic
10078 // without punting it entirely to a software path)
10079 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10081 amplitude = rsurface.texture->tcmods[0].parms[1];
10082 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10083 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10085 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10086 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)
10088 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10089 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10092 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10093 rsurface.texcoordtexture2f_bufferobject = 0;
10094 rsurface.texcoordtexture2f_bufferoffset = 0;
10096 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10097 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10098 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10099 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10102 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10105 const msurface_t *surface = texturesurfacelist[0];
10106 const msurface_t *surface2;
10111 // TODO: lock all array ranges before render, rather than on each surface
10112 if (texturenumsurfaces == 1)
10113 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);
10114 else if (r_batchmode.integer == 2)
10116 #define MAXBATCHTRIANGLES 4096
10117 int batchtriangles = 0;
10118 static int batchelements[MAXBATCHTRIANGLES*3];
10119 for (i = 0;i < texturenumsurfaces;i = j)
10121 surface = texturesurfacelist[i];
10123 if (surface->num_triangles > MAXBATCHTRIANGLES)
10125 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10128 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10129 batchtriangles = surface->num_triangles;
10130 firstvertex = surface->num_firstvertex;
10131 endvertex = surface->num_firstvertex + surface->num_vertices;
10132 for (;j < texturenumsurfaces;j++)
10134 surface2 = texturesurfacelist[j];
10135 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10137 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10138 batchtriangles += surface2->num_triangles;
10139 firstvertex = min(firstvertex, surface2->num_firstvertex);
10140 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10142 surface2 = texturesurfacelist[j-1];
10143 numvertices = endvertex - firstvertex;
10144 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10147 else if (r_batchmode.integer == 1)
10149 for (i = 0;i < texturenumsurfaces;i = j)
10151 surface = texturesurfacelist[i];
10152 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10153 if (texturesurfacelist[j] != surface2)
10155 surface2 = texturesurfacelist[j-1];
10156 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10157 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10158 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10163 for (i = 0;i < texturenumsurfaces;i++)
10165 surface = texturesurfacelist[i];
10166 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);
10171 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10173 switch(vid.renderpath)
10175 case RENDERPATH_CGGL:
10177 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10178 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10181 case RENDERPATH_GL20:
10182 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10183 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10185 case RENDERPATH_GL13:
10186 case RENDERPATH_GL11:
10187 R_Mesh_TexBind(0, surface->lightmaptexture);
10192 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10194 // pick the closest matching water plane and bind textures
10195 int planeindex, vertexindex;
10199 r_waterstate_waterplane_t *p, *bestp;
10202 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10205 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10207 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10208 d += fabs(PlaneDiff(vert, &p->plane));
10210 if (bestd > d || !bestp)
10216 switch(vid.renderpath)
10218 case RENDERPATH_CGGL:
10220 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10221 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10224 case RENDERPATH_GL20:
10225 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10226 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10228 case RENDERPATH_GL13:
10229 case RENDERPATH_GL11:
10234 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10237 const msurface_t *surface;
10238 if (r_waterstate.renderingscene)
10240 for (i = 0;i < texturenumsurfaces;i++)
10242 surface = texturesurfacelist[i];
10243 RSurf_BindLightmapForSurface(surface);
10244 RSurf_BindReflectionForSurface(surface);
10245 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);
10249 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10253 const msurface_t *surface = texturesurfacelist[0];
10254 const msurface_t *surface2;
10259 if (texturenumsurfaces == 1)
10261 RSurf_BindLightmapForSurface(surface);
10262 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);
10264 else if (r_batchmode.integer == 2)
10266 #define MAXBATCHTRIANGLES 4096
10267 int batchtriangles = 0;
10268 static int batchelements[MAXBATCHTRIANGLES*3];
10269 for (i = 0;i < texturenumsurfaces;i = j)
10271 surface = texturesurfacelist[i];
10272 RSurf_BindLightmapForSurface(surface);
10274 if (surface->num_triangles > MAXBATCHTRIANGLES)
10276 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);
10279 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10280 batchtriangles = surface->num_triangles;
10281 firstvertex = surface->num_firstvertex;
10282 endvertex = surface->num_firstvertex + surface->num_vertices;
10283 for (;j < texturenumsurfaces;j++)
10285 surface2 = texturesurfacelist[j];
10286 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10288 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10289 batchtriangles += surface2->num_triangles;
10290 firstvertex = min(firstvertex, surface2->num_firstvertex);
10291 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10293 surface2 = texturesurfacelist[j-1];
10294 numvertices = endvertex - firstvertex;
10295 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10298 else if (r_batchmode.integer == 1)
10301 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10302 for (i = 0;i < texturenumsurfaces;i = j)
10304 surface = texturesurfacelist[i];
10305 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10306 if (texturesurfacelist[j] != surface2)
10308 Con_Printf(" %i", j - i);
10311 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10313 for (i = 0;i < texturenumsurfaces;i = j)
10315 surface = texturesurfacelist[i];
10316 RSurf_BindLightmapForSurface(surface);
10317 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10318 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10321 Con_Printf(" %i", j - i);
10323 surface2 = texturesurfacelist[j-1];
10324 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10325 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10326 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10334 for (i = 0;i < texturenumsurfaces;i++)
10336 surface = texturesurfacelist[i];
10337 RSurf_BindLightmapForSurface(surface);
10338 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);
10343 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10346 int texturesurfaceindex;
10347 if (r_showsurfaces.integer == 2)
10349 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10351 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10352 for (j = 0;j < surface->num_triangles;j++)
10354 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10355 GL_Color(f, f, f, 1);
10356 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10362 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10364 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10365 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10366 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);
10367 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);
10372 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10374 int texturesurfaceindex;
10378 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10380 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10381 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)
10389 rsurface.lightmapcolor4f = rsurface.array_color4f;
10390 rsurface.lightmapcolor4f_bufferobject = 0;
10391 rsurface.lightmapcolor4f_bufferoffset = 0;
10394 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10396 int texturesurfaceindex;
10402 if (rsurface.lightmapcolor4f)
10404 // generate color arrays for the surfaces in this list
10405 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10407 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10408 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)
10410 f = RSurf_FogVertex(v);
10420 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10422 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10423 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)
10425 f = RSurf_FogVertex(v);
10433 rsurface.lightmapcolor4f = rsurface.array_color4f;
10434 rsurface.lightmapcolor4f_bufferobject = 0;
10435 rsurface.lightmapcolor4f_bufferoffset = 0;
10438 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10440 int texturesurfaceindex;
10446 if (!rsurface.lightmapcolor4f)
10448 // generate color arrays for the surfaces in this list
10449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10451 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10452 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)
10454 f = RSurf_FogVertex(v);
10455 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10456 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10457 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10461 rsurface.lightmapcolor4f = rsurface.array_color4f;
10462 rsurface.lightmapcolor4f_bufferobject = 0;
10463 rsurface.lightmapcolor4f_bufferoffset = 0;
10466 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10468 int texturesurfaceindex;
10472 if (!rsurface.lightmapcolor4f)
10474 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10476 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10477 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)
10485 rsurface.lightmapcolor4f = rsurface.array_color4f;
10486 rsurface.lightmapcolor4f_bufferobject = 0;
10487 rsurface.lightmapcolor4f_bufferoffset = 0;
10490 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10492 int texturesurfaceindex;
10496 if (!rsurface.lightmapcolor4f)
10498 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10500 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10501 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)
10503 c2[0] = c[0] + r_refdef.scene.ambient;
10504 c2[1] = c[1] + r_refdef.scene.ambient;
10505 c2[2] = c[2] + r_refdef.scene.ambient;
10509 rsurface.lightmapcolor4f = rsurface.array_color4f;
10510 rsurface.lightmapcolor4f_bufferobject = 0;
10511 rsurface.lightmapcolor4f_bufferoffset = 0;
10514 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10517 rsurface.lightmapcolor4f = NULL;
10518 rsurface.lightmapcolor4f_bufferobject = 0;
10519 rsurface.lightmapcolor4f_bufferoffset = 0;
10520 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10521 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10522 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10523 GL_Color(r, g, b, a);
10524 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10527 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10529 // TODO: optimize applyfog && applycolor case
10530 // just apply fog if necessary, and tint the fog color array if necessary
10531 rsurface.lightmapcolor4f = NULL;
10532 rsurface.lightmapcolor4f_bufferobject = 0;
10533 rsurface.lightmapcolor4f_bufferoffset = 0;
10534 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10535 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10536 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10537 GL_Color(r, g, b, a);
10538 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10541 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10543 int texturesurfaceindex;
10547 if (texturesurfacelist[0]->lightmapinfo)
10549 // generate color arrays for the surfaces in this list
10550 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10552 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10553 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10555 if (surface->lightmapinfo->samples)
10557 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10558 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10559 VectorScale(lm, scale, c);
10560 if (surface->lightmapinfo->styles[1] != 255)
10562 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10564 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10565 VectorMA(c, scale, lm, c);
10566 if (surface->lightmapinfo->styles[2] != 255)
10569 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10570 VectorMA(c, scale, lm, c);
10571 if (surface->lightmapinfo->styles[3] != 255)
10574 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10575 VectorMA(c, scale, lm, c);
10585 rsurface.lightmapcolor4f = rsurface.array_color4f;
10586 rsurface.lightmapcolor4f_bufferobject = 0;
10587 rsurface.lightmapcolor4f_bufferoffset = 0;
10591 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10592 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10593 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10595 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10596 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10597 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10598 GL_Color(r, g, b, a);
10599 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10602 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10604 int texturesurfaceindex;
10611 vec3_t ambientcolor;
10612 vec3_t diffusecolor;
10616 VectorCopy(rsurface.modellight_lightdir, lightdir);
10617 f = 0.5f * r_refdef.lightmapintensity;
10618 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10619 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10620 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10621 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10622 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10623 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10625 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10627 // generate color arrays for the surfaces in this list
10628 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10630 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10631 int numverts = surface->num_vertices;
10632 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10633 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10634 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10635 // q3-style directional shading
10636 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10638 if ((f = DotProduct(n, lightdir)) > 0)
10639 VectorMA(ambientcolor, f, diffusecolor, c);
10641 VectorCopy(ambientcolor, c);
10649 rsurface.lightmapcolor4f = rsurface.array_color4f;
10650 rsurface.lightmapcolor4f_bufferobject = 0;
10651 rsurface.lightmapcolor4f_bufferoffset = 0;
10652 *applycolor = false;
10656 *r = ambientcolor[0];
10657 *g = ambientcolor[1];
10658 *b = ambientcolor[2];
10659 rsurface.lightmapcolor4f = NULL;
10660 rsurface.lightmapcolor4f_bufferobject = 0;
10661 rsurface.lightmapcolor4f_bufferoffset = 0;
10665 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10667 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10668 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10669 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10670 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10671 GL_Color(r, g, b, a);
10672 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10675 void RSurf_SetupDepthAndCulling(void)
10677 // submodels are biased to avoid z-fighting with world surfaces that they
10678 // may be exactly overlapping (avoids z-fighting artifacts on certain
10679 // doors and things in Quake maps)
10680 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10681 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10682 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10683 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10686 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10688 // transparent sky would be ridiculous
10689 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10691 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10692 skyrenderlater = true;
10693 RSurf_SetupDepthAndCulling();
10694 GL_DepthMask(true);
10695 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10696 // skymasking on them, and Quake3 never did sky masking (unlike
10697 // software Quake and software Quake2), so disable the sky masking
10698 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10699 // and skymasking also looks very bad when noclipping outside the
10700 // level, so don't use it then either.
10701 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10703 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10704 R_Mesh_ColorPointer(NULL, 0, 0);
10705 R_Mesh_ResetTextureState();
10706 if (skyrendermasked)
10708 R_SetupShader_DepthOrShadow();
10709 // depth-only (masking)
10710 GL_ColorMask(0,0,0,0);
10711 // just to make sure that braindead drivers don't draw
10712 // anything despite that colormask...
10713 GL_BlendFunc(GL_ZERO, GL_ONE);
10717 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10719 GL_BlendFunc(GL_ONE, GL_ZERO);
10721 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10722 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10723 if (skyrendermasked)
10724 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10726 R_Mesh_ResetTextureState();
10727 GL_Color(1, 1, 1, 1);
10730 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10731 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10732 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10734 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10736 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10739 // render screenspace normalmap to texture
10740 GL_DepthMask(true);
10741 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10742 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10744 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10746 // render water or distortion background, then blend surface on top
10747 GL_DepthMask(true);
10748 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10749 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10750 GL_DepthMask(false);
10751 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10752 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10753 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10755 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10759 // render surface normally
10760 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10761 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10762 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10763 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10764 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10765 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10767 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10771 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10773 // OpenGL 1.3 path - anything not completely ancient
10774 int texturesurfaceindex;
10775 qboolean applycolor;
10778 const texturelayer_t *layer;
10779 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10781 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10784 int layertexrgbscale;
10785 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10787 if (layerindex == 0)
10788 GL_AlphaTest(true);
10791 GL_AlphaTest(false);
10792 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10795 GL_DepthMask(layer->depthmask && writedepth);
10796 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10797 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10799 layertexrgbscale = 4;
10800 VectorScale(layer->color, 0.25f, layercolor);
10802 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10804 layertexrgbscale = 2;
10805 VectorScale(layer->color, 0.5f, layercolor);
10809 layertexrgbscale = 1;
10810 VectorScale(layer->color, 1.0f, layercolor);
10812 layercolor[3] = layer->color[3];
10813 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10814 R_Mesh_ColorPointer(NULL, 0, 0);
10815 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10816 switch (layer->type)
10818 case TEXTURELAYERTYPE_LITTEXTURE:
10819 // single-pass lightmapped texture with 2x rgbscale
10820 R_Mesh_TexBind(0, r_texture_white);
10821 R_Mesh_TexMatrix(0, NULL);
10822 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10823 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10824 R_Mesh_TexBind(1, layer->texture);
10825 R_Mesh_TexMatrix(1, &layer->texmatrix);
10826 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10827 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10828 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10829 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10830 else if (rsurface.uselightmaptexture)
10831 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10833 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10835 case TEXTURELAYERTYPE_TEXTURE:
10836 // singletexture unlit texture with transparency support
10837 R_Mesh_TexBind(0, layer->texture);
10838 R_Mesh_TexMatrix(0, &layer->texmatrix);
10839 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10840 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10841 R_Mesh_TexBind(1, 0);
10842 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10843 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10845 case TEXTURELAYERTYPE_FOG:
10846 // singletexture fogging
10847 if (layer->texture)
10849 R_Mesh_TexBind(0, layer->texture);
10850 R_Mesh_TexMatrix(0, &layer->texmatrix);
10851 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10852 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10856 R_Mesh_TexBind(0, 0);
10857 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10859 R_Mesh_TexBind(1, 0);
10860 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10861 // generate a color array for the fog pass
10862 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10863 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10869 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10870 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)
10872 f = 1 - RSurf_FogVertex(v);
10873 c[0] = layercolor[0];
10874 c[1] = layercolor[1];
10875 c[2] = layercolor[2];
10876 c[3] = f * layercolor[3];
10879 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10882 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10886 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10888 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10889 GL_AlphaTest(false);
10893 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10895 // OpenGL 1.1 - crusty old voodoo path
10896 int texturesurfaceindex;
10899 const texturelayer_t *layer;
10900 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10902 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10904 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10906 if (layerindex == 0)
10907 GL_AlphaTest(true);
10910 GL_AlphaTest(false);
10911 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10914 GL_DepthMask(layer->depthmask && writedepth);
10915 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10916 R_Mesh_ColorPointer(NULL, 0, 0);
10917 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10918 switch (layer->type)
10920 case TEXTURELAYERTYPE_LITTEXTURE:
10921 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10923 // two-pass lit texture with 2x rgbscale
10924 // first the lightmap pass
10925 R_Mesh_TexBind(0, r_texture_white);
10926 R_Mesh_TexMatrix(0, NULL);
10927 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10928 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10929 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10930 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10931 else if (rsurface.uselightmaptexture)
10932 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10934 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10935 // then apply the texture to it
10936 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10937 R_Mesh_TexBind(0, layer->texture);
10938 R_Mesh_TexMatrix(0, &layer->texmatrix);
10939 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10940 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10941 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);
10945 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10946 R_Mesh_TexBind(0, layer->texture);
10947 R_Mesh_TexMatrix(0, &layer->texmatrix);
10948 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10949 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10950 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10951 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);
10953 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);
10956 case TEXTURELAYERTYPE_TEXTURE:
10957 // singletexture unlit texture with transparency support
10958 R_Mesh_TexBind(0, layer->texture);
10959 R_Mesh_TexMatrix(0, &layer->texmatrix);
10960 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10961 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10962 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);
10964 case TEXTURELAYERTYPE_FOG:
10965 // singletexture fogging
10966 if (layer->texture)
10968 R_Mesh_TexBind(0, layer->texture);
10969 R_Mesh_TexMatrix(0, &layer->texmatrix);
10970 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10971 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10975 R_Mesh_TexBind(0, 0);
10976 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10978 // generate a color array for the fog pass
10979 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10980 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10986 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10987 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)
10989 f = 1 - RSurf_FogVertex(v);
10990 c[0] = layer->color[0];
10991 c[1] = layer->color[1];
10992 c[2] = layer->color[2];
10993 c[3] = f * layer->color[3];
10996 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10999 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11003 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11005 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11006 GL_AlphaTest(false);
11010 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11014 GL_AlphaTest(false);
11015 R_Mesh_ColorPointer(NULL, 0, 0);
11016 R_Mesh_ResetTextureState();
11017 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11019 if(rsurface.texture && rsurface.texture->currentskinframe)
11021 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11022 c[3] *= rsurface.texture->currentalpha;
11032 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11034 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11035 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11036 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11039 // brighten it up (as texture value 127 means "unlit")
11040 c[0] *= 2 * r_refdef.view.colorscale;
11041 c[1] *= 2 * r_refdef.view.colorscale;
11042 c[2] *= 2 * r_refdef.view.colorscale;
11044 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11045 c[3] *= r_wateralpha.value;
11047 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11049 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11050 GL_DepthMask(false);
11052 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11054 GL_BlendFunc(GL_ONE, GL_ONE);
11055 GL_DepthMask(false);
11057 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11059 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11060 GL_DepthMask(false);
11062 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11064 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11065 GL_DepthMask(false);
11069 GL_BlendFunc(GL_ONE, GL_ZERO);
11070 GL_DepthMask(writedepth);
11073 rsurface.lightmapcolor4f = NULL;
11075 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11077 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11079 rsurface.lightmapcolor4f = NULL;
11080 rsurface.lightmapcolor4f_bufferobject = 0;
11081 rsurface.lightmapcolor4f_bufferoffset = 0;
11083 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11085 qboolean applycolor = true;
11088 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11090 r_refdef.lightmapintensity = 1;
11091 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11092 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11096 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11098 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11099 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11100 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11103 if(!rsurface.lightmapcolor4f)
11104 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11106 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11107 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11108 if(r_refdef.fogenabled)
11109 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11111 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11112 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11115 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11118 RSurf_SetupDepthAndCulling();
11119 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11121 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11124 switch (vid.renderpath)
11126 case RENDERPATH_GL20:
11127 case RENDERPATH_CGGL:
11128 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11130 case RENDERPATH_GL13:
11131 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11133 case RENDERPATH_GL11:
11134 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11140 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11143 RSurf_SetupDepthAndCulling();
11144 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11146 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11149 switch (vid.renderpath)
11151 case RENDERPATH_GL20:
11152 case RENDERPATH_CGGL:
11153 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11155 case RENDERPATH_GL13:
11156 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11158 case RENDERPATH_GL11:
11159 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11165 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11168 int texturenumsurfaces, endsurface;
11169 texture_t *texture;
11170 const msurface_t *surface;
11171 const msurface_t *texturesurfacelist[256];
11173 // if the model is static it doesn't matter what value we give for
11174 // wantnormals and wanttangents, so this logic uses only rules applicable
11175 // to a model, knowing that they are meaningless otherwise
11176 if (ent == r_refdef.scene.worldentity)
11177 RSurf_ActiveWorldEntity();
11178 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11179 RSurf_ActiveModelEntity(ent, false, false, false);
11182 switch (vid.renderpath)
11184 case RENDERPATH_GL20:
11185 case RENDERPATH_CGGL:
11186 RSurf_ActiveModelEntity(ent, true, true, false);
11188 case RENDERPATH_GL13:
11189 case RENDERPATH_GL11:
11190 RSurf_ActiveModelEntity(ent, true, false, false);
11195 if (r_transparentdepthmasking.integer)
11197 qboolean setup = false;
11198 for (i = 0;i < numsurfaces;i = j)
11201 surface = rsurface.modelsurfaces + surfacelist[i];
11202 texture = surface->texture;
11203 rsurface.texture = R_GetCurrentTexture(texture);
11204 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11205 // scan ahead until we find a different texture
11206 endsurface = min(i + 1024, numsurfaces);
11207 texturenumsurfaces = 0;
11208 texturesurfacelist[texturenumsurfaces++] = surface;
11209 for (;j < endsurface;j++)
11211 surface = rsurface.modelsurfaces + surfacelist[j];
11212 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11214 texturesurfacelist[texturenumsurfaces++] = surface;
11216 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11218 // render the range of surfaces as depth
11222 GL_ColorMask(0,0,0,0);
11224 GL_DepthTest(true);
11225 GL_BlendFunc(GL_ONE, GL_ZERO);
11226 GL_DepthMask(true);
11227 GL_AlphaTest(false);
11228 R_Mesh_ColorPointer(NULL, 0, 0);
11229 R_Mesh_ResetTextureState();
11230 R_SetupShader_DepthOrShadow();
11232 RSurf_SetupDepthAndCulling();
11233 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11234 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11237 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11240 for (i = 0;i < numsurfaces;i = j)
11243 surface = rsurface.modelsurfaces + surfacelist[i];
11244 texture = surface->texture;
11245 rsurface.texture = R_GetCurrentTexture(texture);
11246 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11247 // scan ahead until we find a different texture
11248 endsurface = min(i + 1024, numsurfaces);
11249 texturenumsurfaces = 0;
11250 texturesurfacelist[texturenumsurfaces++] = surface;
11251 for (;j < endsurface;j++)
11253 surface = rsurface.modelsurfaces + surfacelist[j];
11254 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11256 texturesurfacelist[texturenumsurfaces++] = surface;
11258 // render the range of surfaces
11259 if (ent == r_refdef.scene.worldentity)
11260 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11262 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11264 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11265 GL_AlphaTest(false);
11268 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11270 // transparent surfaces get pushed off into the transparent queue
11271 int surfacelistindex;
11272 const msurface_t *surface;
11273 vec3_t tempcenter, center;
11274 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11276 surface = texturesurfacelist[surfacelistindex];
11277 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11278 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11279 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11280 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11281 if (queueentity->transparent_offset) // transparent offset
11283 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11284 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11285 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11287 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11291 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11293 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11297 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11299 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11301 RSurf_SetupDepthAndCulling();
11302 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11303 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11307 if (!rsurface.texture->currentnumlayers)
11309 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11310 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11312 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11314 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11316 RSurf_SetupDepthAndCulling();
11317 GL_AlphaTest(false);
11318 R_Mesh_ColorPointer(NULL, 0, 0);
11319 R_Mesh_ResetTextureState();
11320 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11321 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11322 GL_DepthMask(true);
11323 GL_BlendFunc(GL_ONE, GL_ZERO);
11324 GL_Color(0, 0, 0, 1);
11325 GL_DepthTest(writedepth);
11326 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11328 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11330 RSurf_SetupDepthAndCulling();
11331 GL_AlphaTest(false);
11332 R_Mesh_ColorPointer(NULL, 0, 0);
11333 R_Mesh_ResetTextureState();
11334 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11335 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11336 GL_DepthMask(true);
11337 GL_BlendFunc(GL_ONE, GL_ZERO);
11338 GL_DepthTest(true);
11339 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11341 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11342 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11343 else if (!rsurface.texture->currentnumlayers)
11345 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11347 // in the deferred case, transparent surfaces were queued during prepass
11348 if (!r_shadow_usingdeferredprepass)
11349 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11353 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11354 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11359 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11362 texture_t *texture;
11363 // break the surface list down into batches by texture and use of lightmapping
11364 for (i = 0;i < numsurfaces;i = j)
11367 // texture is the base texture pointer, rsurface.texture is the
11368 // current frame/skin the texture is directing us to use (for example
11369 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11370 // use skin 1 instead)
11371 texture = surfacelist[i]->texture;
11372 rsurface.texture = R_GetCurrentTexture(texture);
11373 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11374 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11376 // if this texture is not the kind we want, skip ahead to the next one
11377 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11381 // simply scan ahead until we find a different texture or lightmap state
11382 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11384 // render the range of surfaces
11385 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11389 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11394 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11396 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11398 RSurf_SetupDepthAndCulling();
11399 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11400 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11404 if (!rsurface.texture->currentnumlayers)
11406 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11407 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11409 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11411 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11413 RSurf_SetupDepthAndCulling();
11414 GL_AlphaTest(false);
11415 R_Mesh_ColorPointer(NULL, 0, 0);
11416 R_Mesh_ResetTextureState();
11417 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11418 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11419 GL_DepthMask(true);
11420 GL_BlendFunc(GL_ONE, GL_ZERO);
11421 GL_Color(0, 0, 0, 1);
11422 GL_DepthTest(writedepth);
11423 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11425 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11427 RSurf_SetupDepthAndCulling();
11428 GL_AlphaTest(false);
11429 R_Mesh_ColorPointer(NULL, 0, 0);
11430 R_Mesh_ResetTextureState();
11431 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11432 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11433 GL_DepthMask(true);
11434 GL_BlendFunc(GL_ONE, GL_ZERO);
11435 GL_DepthTest(true);
11436 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11438 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11439 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11440 else if (!rsurface.texture->currentnumlayers)
11442 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11444 // in the deferred case, transparent surfaces were queued during prepass
11445 if (!r_shadow_usingdeferredprepass)
11446 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11450 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11451 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11456 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11459 texture_t *texture;
11460 // break the surface list down into batches by texture and use of lightmapping
11461 for (i = 0;i < numsurfaces;i = j)
11464 // texture is the base texture pointer, rsurface.texture is the
11465 // current frame/skin the texture is directing us to use (for example
11466 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11467 // use skin 1 instead)
11468 texture = surfacelist[i]->texture;
11469 rsurface.texture = R_GetCurrentTexture(texture);
11470 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11471 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11473 // if this texture is not the kind we want, skip ahead to the next one
11474 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11478 // simply scan ahead until we find a different texture or lightmap state
11479 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11481 // render the range of surfaces
11482 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11486 float locboxvertex3f[6*4*3] =
11488 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11489 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11490 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11491 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11492 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11493 1,0,0, 0,0,0, 0,1,0, 1,1,0
11496 unsigned short locboxelements[6*2*3] =
11501 12,13,14, 12,14,15,
11502 16,17,18, 16,18,19,
11506 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11509 cl_locnode_t *loc = (cl_locnode_t *)ent;
11511 float vertex3f[6*4*3];
11513 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11514 GL_DepthMask(false);
11515 GL_DepthRange(0, 1);
11516 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11517 GL_DepthTest(true);
11518 GL_CullFace(GL_NONE);
11519 R_EntityMatrix(&identitymatrix);
11521 R_Mesh_VertexPointer(vertex3f, 0, 0);
11522 R_Mesh_ColorPointer(NULL, 0, 0);
11523 R_Mesh_ResetTextureState();
11524 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11526 i = surfacelist[0];
11527 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11528 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11529 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11530 surfacelist[0] < 0 ? 0.5f : 0.125f);
11532 if (VectorCompare(loc->mins, loc->maxs))
11534 VectorSet(size, 2, 2, 2);
11535 VectorMA(loc->mins, -0.5f, size, mins);
11539 VectorCopy(loc->mins, mins);
11540 VectorSubtract(loc->maxs, loc->mins, size);
11543 for (i = 0;i < 6*4*3;)
11544 for (j = 0;j < 3;j++, i++)
11545 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11547 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11550 void R_DrawLocs(void)
11553 cl_locnode_t *loc, *nearestloc;
11555 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11556 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11558 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11559 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11563 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11565 if (decalsystem->decals)
11566 Mem_Free(decalsystem->decals);
11567 memset(decalsystem, 0, sizeof(*decalsystem));
11570 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)
11573 tridecal_t *decals;
11576 // expand or initialize the system
11577 if (decalsystem->maxdecals <= decalsystem->numdecals)
11579 decalsystem_t old = *decalsystem;
11580 qboolean useshortelements;
11581 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11582 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11583 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)));
11584 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11585 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11586 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11587 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11588 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11589 if (decalsystem->numdecals)
11590 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11592 Mem_Free(old.decals);
11593 for (i = 0;i < decalsystem->maxdecals*3;i++)
11594 decalsystem->element3i[i] = i;
11595 if (useshortelements)
11596 for (i = 0;i < decalsystem->maxdecals*3;i++)
11597 decalsystem->element3s[i] = i;
11600 // grab a decal and search for another free slot for the next one
11601 decals = decalsystem->decals;
11602 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11603 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11605 decalsystem->freedecal = i;
11606 if (decalsystem->numdecals <= i)
11607 decalsystem->numdecals = i + 1;
11609 // initialize the decal
11611 decal->triangleindex = triangleindex;
11612 decal->surfaceindex = surfaceindex;
11613 decal->decalsequence = decalsequence;
11614 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11615 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11616 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11617 decal->color4ub[0][3] = 255;
11618 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11619 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11620 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11621 decal->color4ub[1][3] = 255;
11622 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11623 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11624 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11625 decal->color4ub[2][3] = 255;
11626 decal->vertex3f[0][0] = v0[0];
11627 decal->vertex3f[0][1] = v0[1];
11628 decal->vertex3f[0][2] = v0[2];
11629 decal->vertex3f[1][0] = v1[0];
11630 decal->vertex3f[1][1] = v1[1];
11631 decal->vertex3f[1][2] = v1[2];
11632 decal->vertex3f[2][0] = v2[0];
11633 decal->vertex3f[2][1] = v2[1];
11634 decal->vertex3f[2][2] = v2[2];
11635 decal->texcoord2f[0][0] = t0[0];
11636 decal->texcoord2f[0][1] = t0[1];
11637 decal->texcoord2f[1][0] = t1[0];
11638 decal->texcoord2f[1][1] = t1[1];
11639 decal->texcoord2f[2][0] = t2[0];
11640 decal->texcoord2f[2][1] = t2[1];
11643 extern cvar_t cl_decals_bias;
11644 extern cvar_t cl_decals_models;
11645 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11646 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)
11648 matrix4x4_t projection;
11649 decalsystem_t *decalsystem;
11652 const float *vertex3f;
11653 const msurface_t *surface;
11654 const msurface_t *surfaces;
11655 const int *surfacelist;
11656 const texture_t *texture;
11658 int numsurfacelist;
11659 int surfacelistindex;
11666 float localorigin[3];
11667 float localnormal[3];
11668 float localmins[3];
11669 float localmaxs[3];
11675 float planes[6][4];
11677 float points[2][9][3];
11681 decalsystem = &ent->decalsystem;
11682 model = ent->model;
11683 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11685 R_DecalSystem_Reset(&ent->decalsystem);
11689 if (!model->brush.data_nodes && !cl_decals_models.integer)
11691 if (decalsystem->model)
11692 R_DecalSystem_Reset(decalsystem);
11696 if (decalsystem->model != model)
11697 R_DecalSystem_Reset(decalsystem);
11698 decalsystem->model = model;
11700 RSurf_ActiveModelEntity(ent, false, false, false);
11702 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11703 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11704 VectorNormalize(localnormal);
11705 localsize = worldsize*rsurface.inversematrixscale;
11706 localmins[0] = localorigin[0] - localsize;
11707 localmins[1] = localorigin[1] - localsize;
11708 localmins[2] = localorigin[2] - localsize;
11709 localmaxs[0] = localorigin[0] + localsize;
11710 localmaxs[1] = localorigin[1] + localsize;
11711 localmaxs[2] = localorigin[2] + localsize;
11713 //VectorCopy(localnormal, planes[4]);
11714 //VectorVectors(planes[4], planes[2], planes[0]);
11715 AnglesFromVectors(angles, localnormal, NULL, false);
11716 AngleVectors(angles, planes[0], planes[2], planes[4]);
11717 VectorNegate(planes[0], planes[1]);
11718 VectorNegate(planes[2], planes[3]);
11719 VectorNegate(planes[4], planes[5]);
11720 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11721 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11722 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11723 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11724 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11725 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11730 matrix4x4_t forwardprojection;
11731 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11732 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11737 float projectionvector[4][3];
11738 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11739 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11740 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11741 projectionvector[0][0] = planes[0][0] * ilocalsize;
11742 projectionvector[0][1] = planes[1][0] * ilocalsize;
11743 projectionvector[0][2] = planes[2][0] * ilocalsize;
11744 projectionvector[1][0] = planes[0][1] * ilocalsize;
11745 projectionvector[1][1] = planes[1][1] * ilocalsize;
11746 projectionvector[1][2] = planes[2][1] * ilocalsize;
11747 projectionvector[2][0] = planes[0][2] * ilocalsize;
11748 projectionvector[2][1] = planes[1][2] * ilocalsize;
11749 projectionvector[2][2] = planes[2][2] * ilocalsize;
11750 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11751 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11752 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11753 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11757 dynamic = model->surfmesh.isanimated;
11758 vertex3f = rsurface.modelvertex3f;
11759 numsurfacelist = model->nummodelsurfaces;
11760 surfacelist = model->sortedmodelsurfaces;
11761 surfaces = model->data_surfaces;
11762 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11764 surfaceindex = surfacelist[surfacelistindex];
11765 surface = surfaces + surfaceindex;
11766 // check cull box first because it rejects more than any other check
11767 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11769 // skip transparent surfaces
11770 texture = surface->texture;
11771 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11773 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11775 numtriangles = surface->num_triangles;
11776 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11778 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11780 index = 3*e[cornerindex];
11781 VectorCopy(vertex3f + index, v[cornerindex]);
11784 //TriangleNormal(v[0], v[1], v[2], normal);
11785 //if (DotProduct(normal, localnormal) < 0.0f)
11787 // clip by each of the box planes formed from the projection matrix
11788 // if anything survives, we emit the decal
11789 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]);
11792 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]);
11795 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]);
11798 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]);
11801 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]);
11804 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]);
11807 // some part of the triangle survived, so we have to accept it...
11810 // dynamic always uses the original triangle
11812 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11814 index = 3*e[cornerindex];
11815 VectorCopy(vertex3f + index, v[cornerindex]);
11818 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11820 // convert vertex positions to texcoords
11821 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11822 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11823 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11824 // calculate distance fade from the projection origin
11825 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11826 f = bound(0.0f, f, 1.0f);
11827 c[cornerindex][0] = r * f;
11828 c[cornerindex][1] = g * f;
11829 c[cornerindex][2] = b * f;
11830 c[cornerindex][3] = 1.0f;
11831 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11834 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);
11836 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11837 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);
11842 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11843 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)
11845 int renderentityindex;
11846 float worldmins[3];
11847 float worldmaxs[3];
11848 entity_render_t *ent;
11850 if (!cl_decals_newsystem.integer)
11853 worldmins[0] = worldorigin[0] - worldsize;
11854 worldmins[1] = worldorigin[1] - worldsize;
11855 worldmins[2] = worldorigin[2] - worldsize;
11856 worldmaxs[0] = worldorigin[0] + worldsize;
11857 worldmaxs[1] = worldorigin[1] + worldsize;
11858 worldmaxs[2] = worldorigin[2] + worldsize;
11860 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11862 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11864 ent = r_refdef.scene.entities[renderentityindex];
11865 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11868 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11872 typedef struct r_decalsystem_splatqueue_s
11874 vec3_t worldorigin;
11875 vec3_t worldnormal;
11881 r_decalsystem_splatqueue_t;
11883 int r_decalsystem_numqueued = 0;
11884 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11886 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)
11888 r_decalsystem_splatqueue_t *queue;
11890 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11893 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11894 VectorCopy(worldorigin, queue->worldorigin);
11895 VectorCopy(worldnormal, queue->worldnormal);
11896 Vector4Set(queue->color, r, g, b, a);
11897 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11898 queue->worldsize = worldsize;
11899 queue->decalsequence = cl.decalsequence++;
11902 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11905 r_decalsystem_splatqueue_t *queue;
11907 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11908 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);
11909 r_decalsystem_numqueued = 0;
11912 extern cvar_t cl_decals_max;
11913 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11916 decalsystem_t *decalsystem = &ent->decalsystem;
11923 if (!decalsystem->numdecals)
11926 if (r_showsurfaces.integer)
11929 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11931 R_DecalSystem_Reset(decalsystem);
11935 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11936 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11938 if (decalsystem->lastupdatetime)
11939 frametime = (cl.time - decalsystem->lastupdatetime);
11942 decalsystem->lastupdatetime = cl.time;
11943 decal = decalsystem->decals;
11944 numdecals = decalsystem->numdecals;
11946 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11948 if (decal->color4ub[0][3])
11950 decal->lived += frametime;
11951 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11953 memset(decal, 0, sizeof(*decal));
11954 if (decalsystem->freedecal > i)
11955 decalsystem->freedecal = i;
11959 decal = decalsystem->decals;
11960 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11963 // collapse the array by shuffling the tail decals into the gaps
11966 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11967 decalsystem->freedecal++;
11968 if (decalsystem->freedecal == numdecals)
11970 decal[decalsystem->freedecal] = decal[--numdecals];
11973 decalsystem->numdecals = numdecals;
11975 if (numdecals <= 0)
11977 // if there are no decals left, reset decalsystem
11978 R_DecalSystem_Reset(decalsystem);
11982 extern skinframe_t *decalskinframe;
11983 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11986 decalsystem_t *decalsystem = &ent->decalsystem;
11995 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11998 numdecals = decalsystem->numdecals;
12002 if (r_showsurfaces.integer)
12005 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12007 R_DecalSystem_Reset(decalsystem);
12011 // if the model is static it doesn't matter what value we give for
12012 // wantnormals and wanttangents, so this logic uses only rules applicable
12013 // to a model, knowing that they are meaningless otherwise
12014 if (ent == r_refdef.scene.worldentity)
12015 RSurf_ActiveWorldEntity();
12017 RSurf_ActiveModelEntity(ent, false, false, false);
12019 decalsystem->lastupdatetime = cl.time;
12020 decal = decalsystem->decals;
12022 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12024 // update vertex positions for animated models
12025 v3f = decalsystem->vertex3f;
12026 c4f = decalsystem->color4f;
12027 t2f = decalsystem->texcoord2f;
12028 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12030 if (!decal->color4ub[0][3])
12033 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12036 // update color values for fading decals
12037 if (decal->lived >= cl_decals_time.value)
12039 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12040 alpha *= (1.0f/255.0f);
12043 alpha = 1.0f/255.0f;
12045 c4f[ 0] = decal->color4ub[0][0] * alpha;
12046 c4f[ 1] = decal->color4ub[0][1] * alpha;
12047 c4f[ 2] = decal->color4ub[0][2] * alpha;
12049 c4f[ 4] = decal->color4ub[1][0] * alpha;
12050 c4f[ 5] = decal->color4ub[1][1] * alpha;
12051 c4f[ 6] = decal->color4ub[1][2] * alpha;
12053 c4f[ 8] = decal->color4ub[2][0] * alpha;
12054 c4f[ 9] = decal->color4ub[2][1] * alpha;
12055 c4f[10] = decal->color4ub[2][2] * alpha;
12058 t2f[0] = decal->texcoord2f[0][0];
12059 t2f[1] = decal->texcoord2f[0][1];
12060 t2f[2] = decal->texcoord2f[1][0];
12061 t2f[3] = decal->texcoord2f[1][1];
12062 t2f[4] = decal->texcoord2f[2][0];
12063 t2f[5] = decal->texcoord2f[2][1];
12065 // update vertex positions for animated models
12066 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12068 e = rsurface.modelelement3i + 3*decal->triangleindex;
12069 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12070 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12071 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12075 VectorCopy(decal->vertex3f[0], v3f);
12076 VectorCopy(decal->vertex3f[1], v3f + 3);
12077 VectorCopy(decal->vertex3f[2], v3f + 6);
12080 if (r_refdef.fogenabled)
12082 alpha = RSurf_FogVertex(v3f);
12083 VectorScale(c4f, alpha, c4f);
12084 alpha = RSurf_FogVertex(v3f + 3);
12085 VectorScale(c4f + 4, alpha, c4f + 4);
12086 alpha = RSurf_FogVertex(v3f + 6);
12087 VectorScale(c4f + 8, alpha, c4f + 8);
12098 r_refdef.stats.drawndecals += numtris;
12100 // now render the decals all at once
12101 // (this assumes they all use one particle font texture!)
12102 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);
12103 R_Mesh_ResetTextureState();
12104 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12105 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12106 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12107 GL_DepthMask(false);
12108 GL_DepthRange(0, 1);
12109 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12110 GL_DepthTest(true);
12111 GL_CullFace(GL_NONE);
12112 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12113 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12114 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12118 static void R_DrawModelDecals(void)
12122 // fade faster when there are too many decals
12123 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12124 for (i = 0;i < r_refdef.scene.numentities;i++)
12125 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12127 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12128 for (i = 0;i < r_refdef.scene.numentities;i++)
12129 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12130 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12132 R_DecalSystem_ApplySplatEntitiesQueue();
12134 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12135 for (i = 0;i < r_refdef.scene.numentities;i++)
12136 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12138 r_refdef.stats.totaldecals += numdecals;
12140 if (r_showsurfaces.integer)
12143 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12145 for (i = 0;i < r_refdef.scene.numentities;i++)
12147 if (!r_refdef.viewcache.entityvisible[i])
12149 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12150 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12154 extern cvar_t mod_collision_bih;
12155 void R_DrawDebugModel(void)
12157 entity_render_t *ent = rsurface.entity;
12158 int i, j, k, l, flagsmask;
12159 const msurface_t *surface;
12160 dp_model_t *model = ent->model;
12163 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12165 R_Mesh_ColorPointer(NULL, 0, 0);
12166 R_Mesh_ResetTextureState();
12167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12168 GL_DepthRange(0, 1);
12169 GL_DepthTest(!r_showdisabledepthtest.integer);
12170 GL_DepthMask(false);
12171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12173 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12177 qboolean cullbox = ent == r_refdef.scene.worldentity;
12178 const q3mbrush_t *brush;
12179 const bih_t *bih = &model->collision_bih;
12180 const bih_leaf_t *bihleaf;
12181 float vertex3f[3][3];
12182 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12184 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12186 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12188 switch (bihleaf->type)
12191 brush = model->brush.data_brushes + bihleaf->itemindex;
12192 if (brush->colbrushf && brush->colbrushf->numtriangles)
12194 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12195 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);
12196 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12199 case BIH_COLLISIONTRIANGLE:
12200 triangleindex = bihleaf->itemindex;
12201 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12202 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12203 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12204 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12205 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);
12206 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12208 case BIH_RENDERTRIANGLE:
12209 triangleindex = bihleaf->itemindex;
12210 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12211 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12212 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12213 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12214 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);
12215 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12221 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12223 if (r_showtris.integer || r_shownormals.integer)
12225 if (r_showdisabledepthtest.integer)
12227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12228 GL_DepthMask(false);
12232 GL_BlendFunc(GL_ONE, GL_ZERO);
12233 GL_DepthMask(true);
12235 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12237 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12239 rsurface.texture = R_GetCurrentTexture(surface->texture);
12240 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12242 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12243 if (r_showtris.value > 0)
12245 if (!rsurface.texture->currentlayers->depthmask)
12246 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12247 else if (ent == r_refdef.scene.worldentity)
12248 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12250 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12251 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12252 R_Mesh_ColorPointer(NULL, 0, 0);
12253 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12254 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12255 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12256 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);
12257 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12260 if (r_shownormals.value < 0)
12262 qglBegin(GL_LINES);
12263 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12265 VectorCopy(rsurface.vertex3f + l * 3, v);
12266 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12267 qglVertex3f(v[0], v[1], v[2]);
12268 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12269 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12270 qglVertex3f(v[0], v[1], v[2]);
12275 if (r_shownormals.value > 0)
12277 qglBegin(GL_LINES);
12278 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12280 VectorCopy(rsurface.vertex3f + l * 3, v);
12281 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12282 qglVertex3f(v[0], v[1], v[2]);
12283 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12284 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12285 qglVertex3f(v[0], v[1], v[2]);
12289 qglBegin(GL_LINES);
12290 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12292 VectorCopy(rsurface.vertex3f + l * 3, v);
12293 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12294 qglVertex3f(v[0], v[1], v[2]);
12295 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12296 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12297 qglVertex3f(v[0], v[1], v[2]);
12301 qglBegin(GL_LINES);
12302 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12304 VectorCopy(rsurface.vertex3f + l * 3, v);
12305 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12306 qglVertex3f(v[0], v[1], v[2]);
12307 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12308 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12309 qglVertex3f(v[0], v[1], v[2]);
12316 rsurface.texture = NULL;
12320 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12321 int r_maxsurfacelist = 0;
12322 const msurface_t **r_surfacelist = NULL;
12323 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12325 int i, j, endj, flagsmask;
12326 dp_model_t *model = r_refdef.scene.worldmodel;
12327 msurface_t *surfaces;
12328 unsigned char *update;
12329 int numsurfacelist = 0;
12333 if (r_maxsurfacelist < model->num_surfaces)
12335 r_maxsurfacelist = model->num_surfaces;
12337 Mem_Free((msurface_t**)r_surfacelist);
12338 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12341 RSurf_ActiveWorldEntity();
12343 surfaces = model->data_surfaces;
12344 update = model->brushq1.lightmapupdateflags;
12346 // update light styles on this submodel
12347 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12349 model_brush_lightstyleinfo_t *style;
12350 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12352 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12354 int *list = style->surfacelist;
12355 style->value = r_refdef.scene.lightstylevalue[style->style];
12356 for (j = 0;j < style->numsurfaces;j++)
12357 update[list[j]] = true;
12362 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12366 R_DrawDebugModel();
12367 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12371 rsurface.uselightmaptexture = false;
12372 rsurface.texture = NULL;
12373 rsurface.rtlight = NULL;
12374 numsurfacelist = 0;
12375 // add visible surfaces to draw list
12376 for (i = 0;i < model->nummodelsurfaces;i++)
12378 j = model->sortedmodelsurfaces[i];
12379 if (r_refdef.viewcache.world_surfacevisible[j])
12380 r_surfacelist[numsurfacelist++] = surfaces + j;
12382 // update lightmaps if needed
12383 if (model->brushq1.firstrender)
12385 model->brushq1.firstrender = false;
12386 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12388 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12392 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12393 if (r_refdef.viewcache.world_surfacevisible[j])
12395 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12397 // don't do anything if there were no surfaces
12398 if (!numsurfacelist)
12400 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12403 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12404 GL_AlphaTest(false);
12406 // add to stats if desired
12407 if (r_speeds.integer && !skysurfaces && !depthonly)
12409 r_refdef.stats.world_surfaces += numsurfacelist;
12410 for (j = 0;j < numsurfacelist;j++)
12411 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12414 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12417 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12419 int i, j, endj, flagsmask;
12420 dp_model_t *model = ent->model;
12421 msurface_t *surfaces;
12422 unsigned char *update;
12423 int numsurfacelist = 0;
12427 if (r_maxsurfacelist < model->num_surfaces)
12429 r_maxsurfacelist = model->num_surfaces;
12431 Mem_Free((msurface_t **)r_surfacelist);
12432 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12435 // if the model is static it doesn't matter what value we give for
12436 // wantnormals and wanttangents, so this logic uses only rules applicable
12437 // to a model, knowing that they are meaningless otherwise
12438 if (ent == r_refdef.scene.worldentity)
12439 RSurf_ActiveWorldEntity();
12440 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12441 RSurf_ActiveModelEntity(ent, false, false, false);
12443 RSurf_ActiveModelEntity(ent, true, true, true);
12444 else if (depthonly)
12446 switch (vid.renderpath)
12448 case RENDERPATH_GL20:
12449 case RENDERPATH_CGGL:
12450 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12452 case RENDERPATH_GL13:
12453 case RENDERPATH_GL11:
12454 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12460 switch (vid.renderpath)
12462 case RENDERPATH_GL20:
12463 case RENDERPATH_CGGL:
12464 RSurf_ActiveModelEntity(ent, true, true, false);
12466 case RENDERPATH_GL13:
12467 case RENDERPATH_GL11:
12468 RSurf_ActiveModelEntity(ent, true, false, false);
12473 surfaces = model->data_surfaces;
12474 update = model->brushq1.lightmapupdateflags;
12476 // update light styles
12477 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12479 model_brush_lightstyleinfo_t *style;
12480 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12482 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12484 int *list = style->surfacelist;
12485 style->value = r_refdef.scene.lightstylevalue[style->style];
12486 for (j = 0;j < style->numsurfaces;j++)
12487 update[list[j]] = true;
12492 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12496 R_DrawDebugModel();
12497 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12501 rsurface.uselightmaptexture = false;
12502 rsurface.texture = NULL;
12503 rsurface.rtlight = NULL;
12504 numsurfacelist = 0;
12505 // add visible surfaces to draw list
12506 for (i = 0;i < model->nummodelsurfaces;i++)
12507 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12508 // don't do anything if there were no surfaces
12509 if (!numsurfacelist)
12511 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12514 // update lightmaps if needed
12518 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12523 R_BuildLightMap(ent, surfaces + j);
12528 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12530 R_BuildLightMap(ent, surfaces + j);
12531 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12532 GL_AlphaTest(false);
12534 // add to stats if desired
12535 if (r_speeds.integer && !skysurfaces && !depthonly)
12537 r_refdef.stats.entities_surfaces += numsurfacelist;
12538 for (j = 0;j < numsurfacelist;j++)
12539 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12542 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12545 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12547 static texture_t texture;
12548 static msurface_t surface;
12549 const msurface_t *surfacelist = &surface;
12551 // fake enough texture and surface state to render this geometry
12553 texture.update_lastrenderframe = -1; // regenerate this texture
12554 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12555 texture.currentskinframe = skinframe;
12556 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12557 texture.offsetmapping = OFFSETMAPPING_OFF;
12558 texture.offsetscale = 1;
12559 texture.specularscalemod = 1;
12560 texture.specularpowermod = 1;
12562 surface.texture = &texture;
12563 surface.num_triangles = numtriangles;
12564 surface.num_firsttriangle = firsttriangle;
12565 surface.num_vertices = numvertices;
12566 surface.num_firstvertex = firstvertex;
12569 rsurface.texture = R_GetCurrentTexture(surface.texture);
12570 rsurface.uselightmaptexture = false;
12571 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12574 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)
12576 static msurface_t surface;
12577 const msurface_t *surfacelist = &surface;
12579 // fake enough texture and surface state to render this geometry
12581 surface.texture = texture;
12582 surface.num_triangles = numtriangles;
12583 surface.num_firsttriangle = firsttriangle;
12584 surface.num_vertices = numvertices;
12585 surface.num_firstvertex = firstvertex;
12588 rsurface.texture = R_GetCurrentTexture(surface.texture);
12589 rsurface.uselightmaptexture = false;
12590 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);