2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
95 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
96 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
98 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
101 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
102 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
104 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
105 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
106 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
107 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
108 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
109 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
110 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
111 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
113 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
114 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
116 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
117 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
123 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
124 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
126 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
127 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
128 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
129 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
130 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
131 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
132 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
133 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
134 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
136 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
137 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
138 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
139 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
140 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
142 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
143 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
144 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
145 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
147 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
148 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
149 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
150 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
151 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
152 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
153 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
155 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
156 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
157 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
158 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
160 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
162 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
164 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
166 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
167 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
168 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
169 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
170 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
171 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
172 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
173 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
175 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
177 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
179 extern cvar_t v_glslgamma;
181 extern qboolean v_flipped_state;
183 static struct r_bloomstate_s
188 int bloomwidth, bloomheight;
190 int screentexturewidth, screentextureheight;
191 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
193 int bloomtexturewidth, bloomtextureheight;
194 rtexture_t *texture_bloom;
196 // arrays for rendering the screen passes
197 float screentexcoord2f[8];
198 float bloomtexcoord2f[8];
199 float offsettexcoord2f[8];
201 r_viewport_t viewport;
205 r_waterstate_t r_waterstate;
207 /// shadow volume bsp struct with automatically growing nodes buffer
210 rtexture_t *r_texture_blanknormalmap;
211 rtexture_t *r_texture_white;
212 rtexture_t *r_texture_grey128;
213 rtexture_t *r_texture_black;
214 rtexture_t *r_texture_notexture;
215 rtexture_t *r_texture_whitecube;
216 rtexture_t *r_texture_normalizationcube;
217 rtexture_t *r_texture_fogattenuation;
218 rtexture_t *r_texture_gammaramps;
219 unsigned int r_texture_gammaramps_serial;
220 //rtexture_t *r_texture_fogintensity;
221 rtexture_t *r_texture_reflectcube;
223 // TODO: hash lookups?
224 typedef struct cubemapinfo_s
231 int r_texture_numcubemaps;
232 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
234 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
235 unsigned int r_numqueries;
236 unsigned int r_maxqueries;
238 typedef struct r_qwskincache_s
240 char name[MAX_QPATH];
241 skinframe_t *skinframe;
245 static r_qwskincache_t *r_qwskincache;
246 static int r_qwskincache_size;
248 /// vertex coordinates for a quad that covers the screen exactly
249 const float r_screenvertex3f[12] =
257 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
260 for (i = 0;i < verts;i++)
271 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
274 for (i = 0;i < verts;i++)
284 // FIXME: move this to client?
287 if (gamemode == GAME_NEHAHRA)
289 Cvar_Set("gl_fogenable", "0");
290 Cvar_Set("gl_fogdensity", "0.2");
291 Cvar_Set("gl_fogred", "0.3");
292 Cvar_Set("gl_foggreen", "0.3");
293 Cvar_Set("gl_fogblue", "0.3");
295 r_refdef.fog_density = 0;
296 r_refdef.fog_red = 0;
297 r_refdef.fog_green = 0;
298 r_refdef.fog_blue = 0;
299 r_refdef.fog_alpha = 1;
300 r_refdef.fog_start = 0;
301 r_refdef.fog_end = 16384;
302 r_refdef.fog_height = 1<<30;
303 r_refdef.fog_fadedepth = 128;
306 static void R_BuildBlankTextures(void)
308 unsigned char data[4];
309 data[2] = 128; // normal X
310 data[1] = 128; // normal Y
311 data[0] = 255; // normal Z
312 data[3] = 128; // height
313 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
318 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
323 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
328 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
331 static void R_BuildNoTexture(void)
334 unsigned char pix[16][16][4];
335 // this makes a light grey/dark grey checkerboard texture
336 for (y = 0;y < 16;y++)
338 for (x = 0;x < 16;x++)
340 if ((y < 8) ^ (x < 8))
356 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
359 static void R_BuildWhiteCube(void)
361 unsigned char data[6*1*1*4];
362 memset(data, 255, sizeof(data));
363 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
366 static void R_BuildNormalizationCube(void)
370 vec_t s, t, intensity;
373 data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
374 for (side = 0;side < 6;side++)
376 for (y = 0;y < NORMSIZE;y++)
378 for (x = 0;x < NORMSIZE;x++)
380 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
381 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416 intensity = 127.0f / sqrt(DotProduct(v, v));
417 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
418 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
419 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
420 data[((side*64+y)*64+x)*4+3] = 255;
424 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
428 static void R_BuildFogTexture(void)
432 unsigned char data1[FOGWIDTH][4];
433 //unsigned char data2[FOGWIDTH][4];
436 r_refdef.fogmasktable_start = r_refdef.fog_start;
437 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
438 r_refdef.fogmasktable_range = r_refdef.fogrange;
439 r_refdef.fogmasktable_density = r_refdef.fog_density;
441 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
442 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
444 d = (x * r - r_refdef.fogmasktable_start);
445 if(developer_extra.integer)
446 Con_DPrintf("%f ", d);
448 if (r_fog_exp2.integer)
449 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
451 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
452 if(developer_extra.integer)
453 Con_DPrintf(" : %f ", alpha);
454 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
455 if(developer_extra.integer)
456 Con_DPrintf(" = %f\n", alpha);
457 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
460 for (x = 0;x < FOGWIDTH;x++)
462 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
467 //data2[x][0] = 255 - b;
468 //data2[x][1] = 255 - b;
469 //data2[x][2] = 255 - b;
472 if (r_texture_fogattenuation)
474 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
475 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
479 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
480 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
484 //=======================================================================================================================================================
486 static const char *builtinshaderstring =
487 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
488 "// written by Forest 'LordHavoc' Hale\n"
489 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
491 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
494 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
495 "#define USELIGHTMAP\n"
497 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
498 "#define USEEYEVECTOR\n"
501 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
502 "# extension GL_ARB_texture_rectangle : enable\n"
505 "#ifdef USESHADOWMAP2D\n"
506 "# ifdef GL_EXT_gpu_shader4\n"
507 "# extension GL_EXT_gpu_shader4 : enable\n"
509 "# ifdef GL_ARB_texture_gather\n"
510 "# extension GL_ARB_texture_gather : enable\n"
512 "# ifdef GL_AMD_texture_texture4\n"
513 "# extension GL_AMD_texture_texture4 : enable\n"
518 "#ifdef USESHADOWMAPCUBE\n"
519 "# extension GL_EXT_gpu_shader4 : enable\n"
522 "//#ifdef USESHADOWSAMPLER\n"
523 "//# extension GL_ARB_shadow : enable\n"
526 "//#ifdef __GLSL_CG_DATA_TYPES\n"
527 "//# define myhalf half\n"
528 "//# define myhalf2 half2\n"
529 "//# define myhalf3 half3\n"
530 "//# define myhalf4 half4\n"
532 "# define myhalf float\n"
533 "# define myhalf2 vec2\n"
534 "# define myhalf3 vec3\n"
535 "# define myhalf4 vec4\n"
538 "#ifdef VERTEX_SHADER\n"
539 "uniform mat4 ModelViewProjectionMatrix;\n"
542 "#ifdef MODE_DEPTH_OR_SHADOW\n"
543 "#ifdef VERTEX_SHADER\n"
546 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
549 "#else // !MODE_DEPTH_ORSHADOW\n"
554 "#ifdef MODE_SHOWDEPTH\n"
555 "#ifdef VERTEX_SHADER\n"
558 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
559 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
563 "#ifdef FRAGMENT_SHADER\n"
566 " gl_FragColor = gl_Color;\n"
569 "#else // !MODE_SHOWDEPTH\n"
574 "#ifdef MODE_POSTPROCESS\n"
575 "varying vec2 TexCoord1;\n"
576 "varying vec2 TexCoord2;\n"
578 "#ifdef VERTEX_SHADER\n"
581 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
582 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
584 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
589 "#ifdef FRAGMENT_SHADER\n"
590 "uniform sampler2D Texture_First;\n"
592 "uniform sampler2D Texture_Second;\n"
594 "#ifdef USEGAMMARAMPS\n"
595 "uniform sampler2D Texture_GammaRamps;\n"
597 "#ifdef USESATURATION\n"
598 "uniform float Saturation;\n"
600 "#ifdef USEVIEWTINT\n"
601 "uniform vec4 ViewTintColor;\n"
603 "//uncomment these if you want to use them:\n"
604 "uniform vec4 UserVec1;\n"
605 "// uniform vec4 UserVec2;\n"
606 "// uniform vec4 UserVec3;\n"
607 "// uniform vec4 UserVec4;\n"
608 "// uniform float ClientTime;\n"
609 "uniform vec2 PixelSize;\n"
612 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
614 " gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
616 "#ifdef USEVIEWTINT\n"
617 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
620 "#ifdef USEPOSTPROCESSING\n"
621 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
622 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
623 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
624 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
625 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
626 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
627 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
628 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
631 "#ifdef USESATURATION\n"
632 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
633 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
634 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
635 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
638 "#ifdef USEGAMMARAMPS\n"
639 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
640 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
641 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
645 "#else // !MODE_POSTPROCESS\n"
650 "#ifdef MODE_GENERIC\n"
651 "#ifdef USEDIFFUSE\n"
652 "varying vec2 TexCoord1;\n"
654 "#ifdef USESPECULAR\n"
655 "varying vec2 TexCoord2;\n"
657 "#ifdef VERTEX_SHADER\n"
660 " gl_FrontColor = gl_Color;\n"
661 "#ifdef USEDIFFUSE\n"
662 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#ifdef USESPECULAR\n"
665 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
667 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "#ifdef FRAGMENT_SHADER\n"
672 "#ifdef USEDIFFUSE\n"
673 "uniform sampler2D Texture_First;\n"
675 "#ifdef USESPECULAR\n"
676 "uniform sampler2D Texture_Second;\n"
681 " gl_FragColor = gl_Color;\n"
682 "#ifdef USEDIFFUSE\n"
683 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
686 "#ifdef USESPECULAR\n"
687 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
688 "# ifdef USECOLORMAPPING\n"
689 " gl_FragColor *= tex2;\n"
692 " gl_FragColor += tex2;\n"
694 "# ifdef USEVERTEXTEXTUREBLEND\n"
695 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
700 "#else // !MODE_GENERIC\n"
705 "#ifdef MODE_BLOOMBLUR\n"
706 "varying TexCoord;\n"
707 "#ifdef VERTEX_SHADER\n"
710 " gl_FrontColor = gl_Color;\n"
711 " TexCoord = gl_MultiTexCoord0.xy;\n"
712 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
716 "#ifdef FRAGMENT_SHADER\n"
717 "uniform sampler2D Texture_First;\n"
718 "uniform vec4 BloomBlur_Parameters;\n"
723 " vec2 tc = TexCoord;\n"
724 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
725 " tc += BloomBlur_Parameters.xy;\n"
726 " for (i = 1;i < SAMPLES;i++)\n"
728 " color += texture2D(Texture_First, tc).rgb;\n"
729 " tc += BloomBlur_Parameters.xy;\n"
731 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
734 "#else // !MODE_BLOOMBLUR\n"
735 "#ifdef MODE_REFRACTION\n"
736 "varying vec2 TexCoord;\n"
737 "varying vec4 ModelViewProjectionPosition;\n"
738 "uniform mat4 TexMatrix;\n"
739 "#ifdef VERTEX_SHADER\n"
743 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
744 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
745 " ModelViewProjectionPosition = gl_Position;\n"
749 "#ifdef FRAGMENT_SHADER\n"
750 "uniform sampler2D Texture_Normal;\n"
751 "uniform sampler2D Texture_Refraction;\n"
752 "uniform sampler2D Texture_Reflection;\n"
754 "uniform vec4 DistortScaleRefractReflect;\n"
755 "uniform vec4 ScreenScaleRefractReflect;\n"
756 "uniform vec4 ScreenCenterRefractReflect;\n"
757 "uniform vec4 RefractColor;\n"
758 "uniform vec4 ReflectColor;\n"
759 "uniform float ReflectFactor;\n"
760 "uniform float ReflectOffset;\n"
764 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
765 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
766 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
768 " // FIXME temporary hack to detect the case that the reflection\n"
769 " // gets blackened at edges due to leaving the area that contains actual\n"
771 " // Remove this 'ack once we have a better way to stop this thing from\n"
773 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
774 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
775 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
776 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
777 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
778 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
781 "#else // !MODE_REFRACTION\n"
786 "#ifdef MODE_WATER\n"
787 "varying vec2 TexCoord;\n"
788 "varying vec3 EyeVector;\n"
789 "varying vec4 ModelViewProjectionPosition;\n"
790 "#ifdef VERTEX_SHADER\n"
791 "uniform vec3 EyePosition;\n"
792 "uniform mat4 TexMatrix;\n"
796 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
797 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
798 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
799 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
800 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
801 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 " ModelViewProjectionPosition = gl_Position;\n"
806 "#ifdef FRAGMENT_SHADER\n"
807 "uniform sampler2D Texture_Normal;\n"
808 "uniform sampler2D Texture_Refraction;\n"
809 "uniform sampler2D Texture_Reflection;\n"
811 "uniform vec4 DistortScaleRefractReflect;\n"
812 "uniform vec4 ScreenScaleRefractReflect;\n"
813 "uniform vec4 ScreenCenterRefractReflect;\n"
814 "uniform vec4 RefractColor;\n"
815 "uniform vec4 ReflectColor;\n"
816 "uniform float ReflectFactor;\n"
817 "uniform float ReflectOffset;\n"
821 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
822 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
823 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
825 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
826 " // FIXME temporary hack to detect the case that the reflection\n"
827 " // gets blackened at edges due to leaving the area that contains actual\n"
829 " // Remove this 'ack once we have a better way to stop this thing from\n"
831 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
832 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
833 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
834 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
835 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
836 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
837 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
838 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
839 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
840 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
841 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
842 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
845 "#else // !MODE_WATER\n"
850 "// common definitions between vertex shader and fragment shader:\n"
852 "varying vec2 TexCoord;\n"
853 "#ifdef USEVERTEXTEXTUREBLEND\n"
854 "varying vec2 TexCoord2;\n"
856 "#ifdef USELIGHTMAP\n"
857 "varying vec2 TexCoordLightmap;\n"
860 "#ifdef MODE_LIGHTSOURCE\n"
861 "varying vec3 CubeVector;\n"
864 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
865 "varying vec3 LightVector;\n"
868 "#ifdef USEEYEVECTOR\n"
869 "varying vec3 EyeVector;\n"
872 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
875 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
876 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
877 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
878 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
881 "#ifdef USEREFLECTION\n"
882 "varying vec4 ModelViewProjectionPosition;\n"
884 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
885 "uniform vec3 LightPosition;\n"
886 "varying vec4 ModelViewPosition;\n"
889 "#ifdef MODE_LIGHTSOURCE\n"
890 "uniform vec3 LightPosition;\n"
892 "uniform vec3 EyePosition;\n"
893 "#ifdef MODE_LIGHTDIRECTION\n"
894 "uniform vec3 LightDir;\n"
896 "uniform vec4 FogPlane;\n"
898 "#ifdef USESHADOWMAPORTHO\n"
899 "varying vec3 ShadowMapTC;\n"
906 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
908 "// fragment shader specific:\n"
909 "#ifdef FRAGMENT_SHADER\n"
911 "uniform sampler2D Texture_Normal;\n"
912 "uniform sampler2D Texture_Color;\n"
913 "uniform sampler2D Texture_Gloss;\n"
915 "uniform sampler2D Texture_Glow;\n"
917 "#ifdef USEVERTEXTEXTUREBLEND\n"
918 "uniform sampler2D Texture_SecondaryNormal;\n"
919 "uniform sampler2D Texture_SecondaryColor;\n"
920 "uniform sampler2D Texture_SecondaryGloss;\n"
922 "uniform sampler2D Texture_SecondaryGlow;\n"
925 "#ifdef USECOLORMAPPING\n"
926 "uniform sampler2D Texture_Pants;\n"
927 "uniform sampler2D Texture_Shirt;\n"
930 "uniform sampler2D Texture_FogMask;\n"
932 "#ifdef USELIGHTMAP\n"
933 "uniform sampler2D Texture_Lightmap;\n"
935 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
936 "uniform sampler2D Texture_Deluxemap;\n"
938 "#ifdef USEREFLECTION\n"
939 "uniform sampler2D Texture_Reflection;\n"
942 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
943 "uniform sampler2D Texture_ScreenDepth;\n"
944 "uniform sampler2D Texture_ScreenNormalMap;\n"
946 "#ifdef USEDEFERREDLIGHTMAP\n"
947 "uniform sampler2D Texture_ScreenDiffuse;\n"
948 "uniform sampler2D Texture_ScreenSpecular;\n"
951 "uniform myhalf3 Color_Pants;\n"
952 "uniform myhalf3 Color_Shirt;\n"
953 "uniform myhalf3 FogColor;\n"
956 "uniform float FogRangeRecip;\n"
957 "uniform float FogPlaneViewDist;\n"
958 "uniform float FogHeightFade;\n"
959 "float FogVertex(void)\n"
961 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
962 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
964 "#ifdef USEFOGOUTSIDE\n"
965 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
967 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
969 " return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
973 "#ifdef USEOFFSETMAPPING\n"
974 "uniform float OffsetMapping_Scale;\n"
975 "vec2 OffsetMapping(vec2 TexCoord)\n"
977 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
978 " // 14 sample relief mapping: linear search and then binary search\n"
979 " // this basically steps forward a small amount repeatedly until it finds\n"
980 " // itself inside solid, then jitters forward and back using decreasing\n"
981 " // amounts to find the impact\n"
982 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
983 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
984 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 " vec3 RT = vec3(TexCoord, 1);\n"
986 " OffsetVector *= 0.1;\n"
987 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
988 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
994 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
997 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
998 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
999 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1000 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1003 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1004 " // this basically moves forward the full distance, and then backs up based\n"
1005 " // on height of samples\n"
1006 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1007 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1008 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 " TexCoord += OffsetVector;\n"
1010 " OffsetVector *= 0.333;\n"
1011 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1012 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 " return TexCoord;\n"
1017 "#endif // USEOFFSETMAPPING\n"
1019 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1020 "uniform sampler2D Texture_Attenuation;\n"
1021 "uniform samplerCube Texture_Cube;\n"
1024 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1026 "#ifdef USESHADOWMAPRECT\n"
1027 "# ifdef USESHADOWSAMPLER\n"
1028 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1030 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1034 "#ifdef USESHADOWMAP2D\n"
1035 "# ifdef USESHADOWSAMPLER\n"
1036 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1038 "uniform sampler2D Texture_ShadowMap2D;\n"
1042 "#ifdef USESHADOWMAPVSDCT\n"
1043 "uniform samplerCube Texture_CubeProjection;\n"
1046 "#ifdef USESHADOWMAPCUBE\n"
1047 "# ifdef USESHADOWSAMPLER\n"
1048 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1050 "uniform samplerCube Texture_ShadowMapCube;\n"
1054 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1055 "uniform vec2 ShadowMap_TextureScale;\n"
1056 "uniform vec4 ShadowMap_Parameters;\n"
1059 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1060 "# ifdef USESHADOWMAPORTHO\n"
1061 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1063 "# ifdef USESHADOWMAPVSDCT\n"
1064 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1066 " vec3 adir = abs(dir);\n"
1067 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1068 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1069 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1072 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1074 " vec3 adir = abs(dir);\n"
1075 " float ma = adir.z;\n"
1076 " vec4 proj = vec4(dir, 2.5);\n"
1077 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1078 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1079 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1080 " 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"
1084 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1086 "#ifdef USESHADOWMAPCUBE\n"
1087 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1089 " vec3 adir = abs(dir);\n"
1090 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1094 "# ifdef USESHADOWMAPRECT\n"
1095 "float ShadowMapCompare(vec3 dir)\n"
1097 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1099 "# ifdef USESHADOWSAMPLER\n"
1101 "# ifdef USESHADOWMAPPCF\n"
1102 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1103 " 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"
1105 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1110 "# ifdef USESHADOWMAPPCF\n"
1111 "# if USESHADOWMAPPCF > 1\n"
1112 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1113 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1114 " 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"
1115 " 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"
1116 " 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"
1117 " 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"
1118 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1119 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1121 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1122 " vec2 offset = fract(shadowmaptc.xy);\n"
1123 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1124 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1125 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1126 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1127 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1130 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1134 "# ifdef USESHADOWMAPORTHO\n"
1135 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1142 "# ifdef USESHADOWMAP2D\n"
1143 "float ShadowMapCompare(vec3 dir)\n"
1145 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "# ifdef USESHADOWMAPPCF\n"
1150 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1151 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1152 " 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"
1154 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1157 "# ifdef USESHADOWMAPPCF\n"
1158 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1159 "# ifdef GL_ARB_texture_gather\n"
1160 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1162 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1164 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1165 " center *= ShadowMap_TextureScale;\n"
1166 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1167 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1168 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1169 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1170 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1171 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1172 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1174 "# ifdef GL_EXT_gpu_shader4\n"
1175 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1177 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1179 "# if USESHADOWMAPPCF > 1\n"
1180 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1181 " center *= ShadowMap_TextureScale;\n"
1182 " 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"
1183 " 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"
1184 " 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"
1185 " 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"
1186 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1187 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1189 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1190 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1191 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1192 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1193 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1194 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1198 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1209 "# ifdef USESHADOWMAPCUBE\n"
1210 "float ShadowMapCompare(vec3 dir)\n"
1212 " // apply depth texture cubemap as light filter\n"
1213 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1215 "# ifdef USESHADOWSAMPLER\n"
1216 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1218 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1223 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1224 "#endif // FRAGMENT_SHADER\n"
1229 "#ifdef MODE_DEFERREDGEOMETRY\n"
1230 "#ifdef VERTEX_SHADER\n"
1231 "uniform mat4 TexMatrix;\n"
1232 "#ifdef USEVERTEXTEXTUREBLEND\n"
1233 "uniform mat4 BackgroundTexMatrix;\n"
1235 "uniform mat4 ModelViewMatrix;\n"
1238 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1239 "#ifdef USEVERTEXTEXTUREBLEND\n"
1240 " gl_FrontColor = gl_Color;\n"
1241 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 " // transform unnormalized eye direction into tangent space\n"
1245 "#ifdef USEOFFSETMAPPING\n"
1246 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1247 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1248 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1249 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1253 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1254 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1255 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1257 "#endif // VERTEX_SHADER\n"
1259 "#ifdef FRAGMENT_SHADER\n"
1262 "#ifdef USEOFFSETMAPPING\n"
1263 " // apply offsetmapping\n"
1264 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1265 "#define TexCoord TexCoordOffset\n"
1268 "#ifdef USEALPHAKILL\n"
1269 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1273 "#ifdef USEVERTEXTEXTUREBLEND\n"
1274 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1275 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1276 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1277 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#ifdef USEVERTEXTEXTUREBLEND\n"
1281 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1282 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1284 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1285 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1288 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1301 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1304 "#endif // VERTEX_SHADER\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1319 " // calculate viewspace pixel position\n"
1320 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1322 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 " // decode viewspace pixel normal\n"
1325 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 " // surfacenormal = pixel normal in viewspace\n"
1328 " // LightVector = pixel to light in viewspace\n"
1329 " // CubeVector = position in lightspace\n"
1330 " // eyevector = pixel to view in viewspace\n"
1331 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 " // calculate diffuse shading\n"
1335 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1338 "#ifdef USESPECULAR\n"
1339 " // calculate directional shading\n"
1340 " vec3 eyevector = position * -1.0;\n"
1341 "# ifdef USEEXACTSPECULARMATH\n"
1342 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1344 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 " fade *= ShadowMapCompare(CubeVector);\n"
1353 "#ifdef USEDIFFUSE\n"
1354 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1356 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1358 "#ifdef USESPECULAR\n"
1359 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1361 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1364 "# ifdef USECUBEFILTER\n"
1365 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 " gl_FragData[0].rgb *= cubecolor;\n"
1367 " gl_FragData[1].rgb *= cubecolor;\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1384 "#ifdef USESHADOWMAPORTHO\n"
1385 "uniform mat4 ShadowMapMatrix;\n"
1389 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1390 " gl_FrontColor = gl_Color;\n"
1392 " // copy the surface texcoord\n"
1393 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1394 "#ifdef USEVERTEXTEXTUREBLEND\n"
1395 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1397 "#ifdef USELIGHTMAP\n"
1398 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1401 "#ifdef MODE_LIGHTSOURCE\n"
1402 " // transform vertex position into light attenuation/cubemap space\n"
1403 " // (-1 to +1 across the light box)\n"
1404 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1406 "# ifdef USEDIFFUSE\n"
1407 " // transform unnormalized light direction into tangent space\n"
1408 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1409 " // normalize it per pixel)\n"
1410 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1411 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1412 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1413 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1417 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1418 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1419 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1420 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1423 " // transform unnormalized eye direction into tangent space\n"
1424 "#ifdef USEEYEVECTOR\n"
1425 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1426 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1427 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1428 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1432 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1433 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1436 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1437 " VectorS = gl_MultiTexCoord1.xyz;\n"
1438 " VectorT = gl_MultiTexCoord2.xyz;\n"
1439 " VectorR = gl_MultiTexCoord3.xyz;\n"
1442 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1443 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1445 "#ifdef USESHADOWMAPORTHO\n"
1446 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1449 "#ifdef USEREFLECTION\n"
1450 " ModelViewProjectionPosition = gl_Position;\n"
1453 "#endif // VERTEX_SHADER\n"
1458 "#ifdef FRAGMENT_SHADER\n"
1459 "#ifdef USEDEFERREDLIGHTMAP\n"
1460 "uniform myhalf2 PixelToScreenTexCoord;\n"
1461 "uniform myhalf3 DeferredMod_Diffuse;\n"
1462 "uniform myhalf3 DeferredMod_Specular;\n"
1464 "uniform myhalf3 Color_Ambient;\n"
1465 "uniform myhalf3 Color_Diffuse;\n"
1466 "uniform myhalf3 Color_Specular;\n"
1467 "uniform myhalf SpecularPower;\n"
1469 "uniform myhalf3 Color_Glow;\n"
1471 "uniform myhalf Alpha;\n"
1472 "#ifdef USEREFLECTION\n"
1473 "uniform vec4 DistortScaleRefractReflect;\n"
1474 "uniform vec4 ScreenScaleRefractReflect;\n"
1475 "uniform vec4 ScreenCenterRefractReflect;\n"
1476 "uniform myhalf4 ReflectColor;\n"
1478 "#ifdef USEREFLECTCUBE\n"
1479 "uniform mat4 ModelToReflectCube;\n"
1480 "uniform sampler2D Texture_ReflectMask;\n"
1481 "uniform samplerCube Texture_ReflectCube;\n"
1483 "#ifdef MODE_LIGHTDIRECTION\n"
1484 "uniform myhalf3 LightColor;\n"
1486 "#ifdef MODE_LIGHTSOURCE\n"
1487 "uniform myhalf3 LightColor;\n"
1491 "#ifdef USEOFFSETMAPPING\n"
1492 " // apply offsetmapping\n"
1493 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1494 "#define TexCoord TexCoordOffset\n"
1497 " // combine the diffuse textures (base, pants, shirt)\n"
1498 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1499 "#ifdef USEALPHAKILL\n"
1500 " if (color.a < 0.5)\n"
1503 " color.a *= Alpha;\n"
1504 "#ifdef USECOLORMAPPING\n"
1505 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1507 "#ifdef USEVERTEXTEXTUREBLEND\n"
1508 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1509 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1510 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1511 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1513 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1516 " // get the surface normal\n"
1517 "#ifdef USEVERTEXTEXTUREBLEND\n"
1518 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1520 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1523 " // get the material colors\n"
1524 " myhalf3 diffusetex = color.rgb;\n"
1525 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1526 "# ifdef USEVERTEXTEXTUREBLEND\n"
1527 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1529 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1535 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1536 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1537 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1543 "#ifdef MODE_LIGHTSOURCE\n"
1544 " // light source\n"
1545 "#ifdef USEDIFFUSE\n"
1546 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1547 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1548 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1549 "#ifdef USESPECULAR\n"
1550 "#ifdef USEEXACTSPECULARMATH\n"
1551 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1553 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1554 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1556 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1559 " color.rgb = diffusetex * Color_Ambient;\n"
1561 " color.rgb *= LightColor;\n"
1562 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1563 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1564 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1566 "# ifdef USECUBEFILTER\n"
1567 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1569 "#endif // MODE_LIGHTSOURCE\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1576 "#ifdef USEDIFFUSE\n"
1577 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1579 "#define lightcolor LightColor\n"
1580 "#endif // MODE_LIGHTDIRECTION\n"
1581 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1584 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1585 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1586 " // convert modelspace light vector to tangentspace\n"
1587 " myhalf3 lightnormal;\n"
1588 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1589 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1590 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1591 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1592 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1593 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1594 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1595 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1596 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1597 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1598 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1599 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1600 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1601 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1602 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1604 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1605 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1606 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1612 "#ifdef MODE_LIGHTMAP\n"
1613 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1614 "#endif // MODE_LIGHTMAP\n"
1615 "#ifdef MODE_VERTEXCOLOR\n"
1616 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1617 "#endif // MODE_VERTEXCOLOR\n"
1618 "#ifdef MODE_FLATCOLOR\n"
1619 " color.rgb = diffusetex * Color_Ambient;\n"
1620 "#endif // MODE_FLATCOLOR\n"
1626 "# ifdef USEDIFFUSE\n"
1627 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1628 "# ifdef USESPECULAR\n"
1629 "# ifdef USEEXACTSPECULARMATH\n"
1630 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1632 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1633 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1635 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1637 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1640 " color.rgb = diffusetex * Color_Ambient;\n"
1644 "#ifdef USESHADOWMAPORTHO\n"
1645 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1648 "#ifdef USEDEFERREDLIGHTMAP\n"
1649 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1650 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1651 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1655 "#ifdef USEVERTEXTEXTUREBLEND\n"
1656 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1658 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1663 "#ifdef MODE_LIGHTSOURCE\n"
1664 " color.rgb *= myhalf(FogVertex());\n"
1666 " color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1670 " // 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"
1671 "#ifdef USEREFLECTION\n"
1672 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1673 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1674 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1675 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1676 " // FIXME temporary hack to detect the case that the reflection\n"
1677 " // gets blackened at edges due to leaving the area that contains actual\n"
1679 " // Remove this 'ack once we have a better way to stop this thing from\n"
1681 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1682 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1686 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1689 " gl_FragColor = vec4(color);\n"
1691 "#endif // FRAGMENT_SHADER\n"
1693 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1694 "#endif // !MODE_DEFERREDGEOMETRY\n"
1695 "#endif // !MODE_WATER\n"
1696 "#endif // !MODE_REFRACTION\n"
1697 "#endif // !MODE_BLOOMBLUR\n"
1698 "#endif // !MODE_GENERIC\n"
1699 "#endif // !MODE_POSTPROCESS\n"
1700 "#endif // !MODE_SHOWDEPTH\n"
1701 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1705 =========================================================================================================================================================
1709 =========================================================================================================================================================
1713 =========================================================================================================================================================
1717 =========================================================================================================================================================
1721 =========================================================================================================================================================
1725 =========================================================================================================================================================
1729 =========================================================================================================================================================
1732 const char *builtincgshaderstring =
1733 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1734 "// written by Forest 'LordHavoc' Hale\n"
1735 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1737 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1740 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1741 "#define USELIGHTMAP\n"
1743 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1744 "#define USEEYEVECTOR\n"
1747 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1748 "#ifdef VERTEX_SHADER\n"
1751 "float4 gl_Vertex : POSITION,\n"
1752 "uniform float4x4 ModelViewProjectionMatrix,\n"
1753 "out float4 gl_Position : POSITION\n"
1756 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1759 "#else // !MODE_DEPTH_ORSHADOW\n"
1764 "#ifdef MODE_SHOWDEPTH\n"
1765 "#ifdef VERTEX_SHADER\n"
1768 "float4 gl_Vertex : POSITION,\n"
1769 "uniform float4x4 ModelViewProjectionMatrix,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float4 gl_FrontColor : COLOR0\n"
1774 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1775 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1779 "#ifdef FRAGMENT_SHADER\n"
1782 "float4 gl_FrontColor : COLOR0,\n"
1783 "out float4 gl_FragColor : COLOR\n"
1786 " gl_FragColor = gl_FrontColor;\n"
1789 "#else // !MODE_SHOWDEPTH\n"
1794 "#ifdef MODE_POSTPROCESS\n"
1796 "#ifdef VERTEX_SHADER\n"
1799 "float4 gl_Vertex : POSITION,\n"
1800 "uniform float4x4 ModelViewProjectionMatrix,\n"
1801 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1802 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1803 "out float4 gl_Position : POSITION,\n"
1804 "out float2 TexCoord1 : TEXCOORD0,\n"
1805 "out float2 TexCoord2 : TEXCOORD1\n"
1808 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1809 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1811 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1816 "#ifdef FRAGMENT_SHADER\n"
1819 "float2 TexCoord1 : TEXCOORD0,\n"
1820 "float2 TexCoord2 : TEXCOORD1,\n"
1821 "uniform sampler2D Texture_First,\n"
1823 "uniform sampler2D Texture_Second,\n"
1825 "#ifdef USEGAMMARAMPS\n"
1826 "uniform sampler2D Texture_GammaRamps,\n"
1828 "#ifdef USESATURATION\n"
1829 "uniform float Saturation,\n"
1831 "#ifdef USEVIEWTINT\n"
1832 "uniform float4 ViewTintColor,\n"
1834 "uniform float4 UserVec1,\n"
1835 "uniform float4 UserVec2,\n"
1836 "uniform float4 UserVec3,\n"
1837 "uniform float4 UserVec4,\n"
1838 "uniform float ClientTime,\n"
1839 "uniform float2 PixelSize,\n"
1840 "out float4 gl_FragColor : COLOR\n"
1843 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1845 " gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1847 "#ifdef USEVIEWTINT\n"
1848 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1851 "#ifdef USEPOSTPROCESSING\n"
1852 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1853 "// 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"
1854 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1855 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1856 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1857 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1858 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1859 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1862 "#ifdef USESATURATION\n"
1863 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1864 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1865 " //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1866 " gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1869 "#ifdef USEGAMMARAMPS\n"
1870 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1871 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1872 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1876 "#else // !MODE_POSTPROCESS\n"
1881 "#ifdef MODE_GENERIC\n"
1882 "#ifdef VERTEX_SHADER\n"
1885 "float4 gl_Vertex : POSITION,\n"
1886 "uniform float4x4 ModelViewProjectionMatrix,\n"
1887 "float4 gl_Color : COLOR0,\n"
1888 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1889 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1890 "out float4 gl_Position : POSITION,\n"
1891 "out float4 gl_FrontColor : COLOR,\n"
1892 "out float2 TexCoord1 : TEXCOORD0,\n"
1893 "out float2 TexCoord2 : TEXCOORD1\n"
1896 " gl_FrontColor = gl_Color;\n"
1897 "#ifdef USEDIFFUSE\n"
1898 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1900 "#ifdef USESPECULAR\n"
1901 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
1903 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1907 "#ifdef FRAGMENT_SHADER\n"
1911 "float4 gl_FrontColor : COLOR,\n"
1912 "float2 TexCoord1 : TEXCOORD0,\n"
1913 "float2 TexCoord2 : TEXCOORD1,\n"
1914 "#ifdef USEDIFFUSE\n"
1915 "uniform sampler2D Texture_First,\n"
1917 "#ifdef USESPECULAR\n"
1918 "uniform sampler2D Texture_Second,\n"
1920 "out float4 gl_FragColor : COLOR\n"
1923 " gl_FragColor = gl_FrontColor;\n"
1924 "#ifdef USEDIFFUSE\n"
1925 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1928 "#ifdef USESPECULAR\n"
1929 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1930 "# ifdef USECOLORMAPPING\n"
1931 " gl_FragColor *= tex2;\n"
1934 " gl_FragColor += tex2;\n"
1936 "# ifdef USEVERTEXTEXTUREBLEND\n"
1937 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1942 "#else // !MODE_GENERIC\n"
1947 "#ifdef MODE_BLOOMBLUR\n"
1948 "#ifdef VERTEX_SHADER\n"
1951 "float4 gl_Vertex : POSITION,\n"
1952 "uniform float4x4 ModelViewProjectionMatrix,\n"
1953 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1954 "out float4 gl_Position : POSITION,\n"
1955 "out float2 TexCoord : TEXCOORD0\n"
1958 " TexCoord = gl_MultiTexCoord0.xy;\n"
1959 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1963 "#ifdef FRAGMENT_SHADER\n"
1967 "float2 TexCoord : TEXCOORD0,\n"
1968 "uniform sampler2D Texture_First,\n"
1969 "uniform float4 BloomBlur_Parameters,\n"
1970 "out float4 gl_FragColor : COLOR\n"
1974 " float2 tc = TexCoord;\n"
1975 " float3 color = tex2D(Texture_First, tc).rgb;\n"
1976 " tc += BloomBlur_Parameters.xy;\n"
1977 " for (i = 1;i < SAMPLES;i++)\n"
1979 " color += tex2D(Texture_First, tc).rgb;\n"
1980 " tc += BloomBlur_Parameters.xy;\n"
1982 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1985 "#else // !MODE_BLOOMBLUR\n"
1986 "#ifdef MODE_REFRACTION\n"
1987 "#ifdef VERTEX_SHADER\n"
1990 "float4 gl_Vertex : POSITION,\n"
1991 "uniform float4x4 ModelViewProjectionMatrix,\n"
1992 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1993 "uniform float4x4 TexMatrix,\n"
1994 "uniform float3 EyePosition,\n"
1995 "out float4 gl_Position : POSITION,\n"
1996 "out float2 TexCoord : TEXCOORD0,\n"
1997 "out float3 EyeVector : TEXCOORD1,\n"
1998 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2001 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2002 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2003 " ModelViewProjectionPosition = gl_Position;\n"
2007 "#ifdef FRAGMENT_SHADER\n"
2010 "float2 TexCoord : TEXCOORD0,\n"
2011 "float3 EyeVector : TEXCOORD1,\n"
2012 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2013 "uniform sampler2D Texture_Normal,\n"
2014 "uniform sampler2D Texture_Refraction,\n"
2015 "uniform sampler2D Texture_Reflection,\n"
2016 "uniform float4 DistortScaleRefractReflect,\n"
2017 "uniform float4 ScreenScaleRefractReflect,\n"
2018 "uniform float4 ScreenCenterRefractReflect,\n"
2019 "uniform float4 RefractColor,\n"
2020 "out float4 gl_FragColor : COLOR\n"
2023 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2024 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2025 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2026 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2027 " // FIXME temporary hack to detect the case that the reflection\n"
2028 " // gets blackened at edges due to leaving the area that contains actual\n"
2030 " // Remove this 'ack once we have a better way to stop this thing from\n"
2032 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2033 " 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 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2037 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2040 "#else // !MODE_REFRACTION\n"
2045 "#ifdef MODE_WATER\n"
2046 "#ifdef VERTEX_SHADER\n"
2050 "float4 gl_Vertex : POSITION,\n"
2051 "uniform float4x4 ModelViewProjectionMatrix,\n"
2052 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2053 "uniform float4x4 TexMatrix,\n"
2054 "uniform float3 EyePosition,\n"
2055 "out float4 gl_Position : POSITION,\n"
2056 "out float2 TexCoord : TEXCOORD0,\n"
2057 "out float3 EyeVector : TEXCOORD1,\n"
2058 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2061 " TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2062 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2063 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2064 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2065 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2066 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2067 " ModelViewProjectionPosition = gl_Position;\n"
2071 "#ifdef FRAGMENT_SHADER\n"
2074 "float2 TexCoord : TEXCOORD0,\n"
2075 "float3 EyeVector : TEXCOORD1,\n"
2076 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2077 "uniform sampler2D Texture_Normal,\n"
2078 "uniform sampler2D Texture_Refraction,\n"
2079 "uniform sampler2D Texture_Reflection,\n"
2080 "uniform float4 DistortScaleRefractReflect,\n"
2081 "uniform float4 ScreenScaleRefractReflect,\n"
2082 "uniform float4 ScreenCenterRefractReflect,\n"
2083 "uniform float4 RefractColor,\n"
2084 "uniform float4 ReflectColor,\n"
2085 "uniform float ReflectFactor,\n"
2086 "uniform float ReflectOffset,\n"
2087 "out float4 gl_FragColor : COLOR\n"
2090 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2091 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2092 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2093 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2094 " // FIXME temporary hack to detect the case that the reflection\n"
2095 " // gets blackened at edges due to leaving the area that contains actual\n"
2097 " // Remove this 'ack once we have a better way to stop this thing from\n"
2099 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2100 " 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 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2104 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\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 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2109 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2110 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2113 "#else // !MODE_WATER\n"
2118 "// 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"
2120 "// fragment shader specific:\n"
2121 "#ifdef FRAGMENT_SHADER\n"
2124 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2127 "#ifdef USEFOGOUTSIDE\n"
2128 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2130 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2132 " return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2136 "#ifdef USEOFFSETMAPPING\n"
2137 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2139 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2140 " // 14 sample relief mapping: linear search and then binary search\n"
2141 " // this basically steps forward a small amount repeatedly until it finds\n"
2142 " // itself inside solid, then jitters forward and back using decreasing\n"
2143 " // amounts to find the impact\n"
2144 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2145 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2146 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2147 " float3 RT = float3(TexCoord, 1);\n"
2148 " OffsetVector *= 0.1;\n"
2149 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
2159 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2160 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2161 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2162 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2165 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2166 " // this basically moves forward the full distance, and then backs up based\n"
2167 " // on height of samples\n"
2168 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2169 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2170 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2171 " TexCoord += OffsetVector;\n"
2172 " OffsetVector *= 0.333;\n"
2173 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2174 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2175 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2176 " return TexCoord;\n"
2179 "#endif // USEOFFSETMAPPING\n"
2181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2182 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2183 "# ifdef USESHADOWMAPORTHO\n"
2184 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2186 "# ifdef USESHADOWMAPVSDCT\n"
2187 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2189 " float3 adir = abs(dir);\n"
2190 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2191 " float4 proj = texCUBEe(Texture_CubeProjection, dir);\n"
2192 " return float3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2195 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2197 " float3 adir = abs(dir);\n"
2198 " float ma = adir.z;\n"
2199 " float4 proj = float4(dir, 2.5);\n"
2200 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2201 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2202 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2203 " 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"
2207 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2209 "#ifdef USESHADOWMAPCUBE\n"
2210 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2212 " float3 adir = abs(dir);\n"
2213 " return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2217 "# ifdef USESHADOWMAPRECT\n"
2218 "#ifdef USESHADOWMAPVSDCT\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2221 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2224 "#ifdef USESHADOWMAPVSDCT\n"
2225 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2227 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2230 "# ifdef USESHADOWSAMPLER\n"
2232 "# ifdef USESHADOWMAPPCF\n"
2233 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2234 " 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"
2236 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2241 "# ifdef USESHADOWMAPPCF\n"
2242 "# if USESHADOWMAPPCF > 1\n"
2243 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2244 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2245 " 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"
2246 " 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"
2247 " 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"
2248 " 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"
2249 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2250 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2252 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2253 " float2 offset = frac(shadowmaptc.xy);\n"
2254 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2255 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2256 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2257 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2258 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2261 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2265 "# ifdef USESHADOWMAPORTHO\n"
2266 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2273 "# ifdef USESHADOWMAP2D\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2277 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2280 "#ifdef USESHADOWMAPVSDCT\n"
2281 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2283 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2287 "# ifdef USESHADOWSAMPLER\n"
2288 "# ifdef USESHADOWMAPPCF\n"
2289 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
2290 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2291 " 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"
2293 " f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2296 "# ifdef USESHADOWMAPPCF\n"
2297 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2298 "# ifdef GL_ARB_texture_gather\n"
2299 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2301 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2303 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2304 " center *= ShadowMap_TextureScale;\n"
2305 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2306 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2307 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2308 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2309 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2310 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2311 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2313 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale) \n"
2314 "# if USESHADOWMAPPCF > 1\n"
2315 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2316 " center *= ShadowMap_TextureScale;\n"
2317 " 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"
2318 " 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"
2319 " 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"
2320 " 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"
2321 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2322 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2324 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2325 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2326 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2327 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2328 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2329 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2333 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2336 "# ifdef USESHADOWMAPORTHO\n"
2337 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2347 " // apply depth texture cubemap as light filter\n"
2348 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2350 "# ifdef USESHADOWSAMPLER\n"
2351 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2353 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2396 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 " gl_FrontColor = gl_Color;\n"
2399 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2402 " // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2410 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2415 "#endif // VERTEX_SHADER\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2429 "uniform sampler2D Texture_Gloss,\n"
2430 "#ifdef USEVERTEXTEXTUREBLEND\n"
2431 "uniform sampler2D Texture_SecondaryNormal,\n"
2432 "uniform sampler2D Texture_SecondaryGloss,\n"
2434 "#ifdef USEOFFSETMAPPING\n"
2435 "uniform float OffsetMapping_Scale,\n"
2437 "uniform half SpecularPower,\n"
2438 "out float4 gl_FragColor : COLOR\n"
2441 " float2 TexCoord = TexCoordBoth.xy;\n"
2442 "#ifdef USEOFFSETMAPPING\n"
2443 " // apply offsetmapping\n"
2444 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2445 "#define TexCoord TexCoordOffset\n"
2448 "#ifdef USEALPHAKILL\n"
2449 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2453 "#ifdef USEVERTEXTEXTUREBLEND\n"
2454 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2455 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2456 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2457 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2460 "#ifdef USEVERTEXTEXTUREBLEND\n"
2461 " float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2462 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2464 " float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2465 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2468 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2470 "#endif // FRAGMENT_SHADER\n"
2471 "#else // !MODE_DEFERREDGEOMETRY\n"
2476 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2477 "#ifdef VERTEX_SHADER\n"
2480 "float4 gl_Vertex : POSITION,\n"
2481 "uniform float4x4 ModelViewProjectionMatrix,\n"
2482 "uniform float4x4 ModelViewMatrix,\n"
2483 "out float4 gl_Position : POSITION,\n"
2484 "out float4 ModelViewPosition : TEXCOORD0\n"
2487 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2488 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2490 "#endif // VERTEX_SHADER\n"
2492 "#ifdef FRAGMENT_SHADER\n"
2495 "float2 Pixel : WPOS,\n"
2496 "float4 ModelViewPosition : TEXCOORD0,\n"
2497 "uniform float4x4 ViewToLight,\n"
2498 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2499 "uniform float3 LightPosition,\n"
2500 "uniform half2 PixelToScreenTexCoord,\n"
2501 "uniform half3 DeferredColor_Ambient,\n"
2502 "uniform half3 DeferredColor_Diffuse,\n"
2503 "#ifdef USESPECULAR\n"
2504 "uniform half3 DeferredColor_Specular,\n"
2505 "uniform half SpecularPower,\n"
2507 "uniform sampler2D Texture_Attenuation,\n"
2508 "uniform sampler2D Texture_ScreenDepth,\n"
2509 "uniform sampler2D Texture_ScreenNormalMap,\n"
2511 "#ifdef USESHADOWMAPRECT\n"
2512 "# ifdef USESHADOWSAMPLER\n"
2513 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2515 "uniform samplerRECT Texture_ShadowMapRect,\n"
2519 "#ifdef USESHADOWMAP2D\n"
2520 "# ifdef USESHADOWSAMPLER\n"
2521 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2523 "uniform sampler2D Texture_ShadowMap2D,\n"
2527 "#ifdef USESHADOWMAPVSDCT\n"
2528 "uniform samplerCUBE Texture_CubeProjection,\n"
2531 "#ifdef USESHADOWMAPCUBE\n"
2532 "# ifdef USESHADOWSAMPLER\n"
2533 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2535 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2539 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2540 "uniform float2 ShadowMap_TextureScale,\n"
2541 "uniform float4 ShadowMap_Parameters,\n"
2544 "out float4 gl_FragData0 : COLOR0,\n"
2545 "out float4 gl_FragData1 : COLOR1\n"
2548 " // calculate viewspace pixel position\n"
2549 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2550 " ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2551 " float3 position;\n"
2552 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2553 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2554 " // decode viewspace pixel normal\n"
2555 " half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2556 " half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2557 " // surfacenormal = pixel normal in viewspace\n"
2558 " // LightVector = pixel to light in viewspace\n"
2559 " // CubeVector = position in lightspace\n"
2560 " // eyevector = pixel to view in viewspace\n"
2561 " float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2562 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2563 "#ifdef USEDIFFUSE\n"
2564 " // calculate diffuse shading\n"
2565 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2566 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2568 "#ifdef USESPECULAR\n"
2569 " // calculate directional shading\n"
2570 " float3 eyevector = position * -1.0;\n"
2571 "# ifdef USEEXACTSPECULARMATH\n"
2572 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2574 " half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2575 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2579 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2580 " fade *= ShadowMapCompare(CubeVector,\n"
2581 "# if defined(USESHADOWMAP2D)\n"
2582 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2584 "# if defined(USESHADOWMAPRECT)\n"
2585 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2587 "# if defined(USESHADOWMAPCUBE)\n"
2588 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2591 "#ifdef USESHADOWMAPVSDCT\n"
2592 ", Texture_CubeProjection\n"
2597 "#ifdef USEDIFFUSE\n"
2598 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2600 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2602 "#ifdef USESPECULAR\n"
2603 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2605 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2608 "# ifdef USECUBEFILTER\n"
2609 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2610 " gl_FragData0.rgb *= cubecolor;\n"
2611 " gl_FragData1.rgb *= cubecolor;\n"
2614 "#endif // FRAGMENT_SHADER\n"
2615 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2620 "#ifdef VERTEX_SHADER\n"
2623 "float4 gl_Vertex : POSITION,\n"
2624 "uniform float4x4 ModelViewProjectionMatrix,\n"
2625 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2626 "float4 gl_Color : COLOR0,\n"
2628 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2629 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2630 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2631 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2632 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2634 "uniform float3 EyePosition,\n"
2635 "uniform float4x4 TexMatrix,\n"
2636 "#ifdef USEVERTEXTEXTUREBLEND\n"
2637 "uniform float4x4 BackgroundTexMatrix,\n"
2639 "#ifdef MODE_LIGHTSOURCE\n"
2640 "uniform float4x4 ModelToLight,\n"
2642 "#ifdef MODE_LIGHTSOURCE\n"
2643 "uniform float3 LightPosition,\n"
2645 "#ifdef MODE_LIGHTDIRECTION\n"
2646 "uniform float3 LightDir,\n"
2648 "uniform float4 FogPlane,\n"
2649 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2650 "uniform float3 LightPosition,\n"
2652 "#ifdef USESHADOWMAPORTHO\n"
2653 "uniform float4x4 ShadowMapMatrix,\n"
2656 "out float4 gl_FrontColor : COLOR,\n"
2657 "out float4 TexCoordBoth : TEXCOORD0,\n"
2658 "#ifdef USELIGHTMAP\n"
2659 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2661 "#ifdef USEEYEVECTOR\n"
2662 "out float3 EyeVector : TEXCOORD2,\n"
2664 "#ifdef USEREFLECTION\n"
2665 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2668 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2670 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2671 "out float3 LightVector : TEXCOORD5,\n"
2673 "#ifdef MODE_LIGHTSOURCE\n"
2674 "out float3 CubeVector : TEXCOORD3,\n"
2676 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2677 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2678 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2679 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "#ifdef USESHADOWMAPORTHO\n"
2682 "out float3 ShadowMapTC : TEXCOORD8,\n"
2684 "out float4 gl_Position : POSITION\n"
2687 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2688 " gl_FrontColor = gl_Color;\n"
2690 " // copy the surface texcoord\n"
2691 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2692 "#ifdef USEVERTEXTEXTUREBLEND\n"
2693 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2695 "#ifdef USELIGHTMAP\n"
2696 " TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2699 "#ifdef MODE_LIGHTSOURCE\n"
2700 " // transform vertex position into light attenuation/cubemap space\n"
2701 " // (-1 to +1 across the light box)\n"
2702 " CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2704 "# ifdef USEDIFFUSE\n"
2705 " // transform unnormalized light direction into tangent space\n"
2706 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2707 " // normalize it per pixel)\n"
2708 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2709 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2710 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2711 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2715 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2716 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2717 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2718 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2721 " // transform unnormalized eye direction into tangent space\n"
2722 "#ifdef USEEYEVECTOR\n"
2723 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2724 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2725 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2726 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2730 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2731 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2734 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2735 " VectorS = gl_MultiTexCoord1.xyz;\n"
2736 " VectorT = gl_MultiTexCoord2.xyz;\n"
2737 " VectorR = gl_MultiTexCoord3.xyz;\n"
2740 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2741 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2743 "#ifdef USESHADOWMAPORTHO\n"
2744 " ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2747 "#ifdef USEREFLECTION\n"
2748 " ModelViewProjectionPosition = gl_Position;\n"
2751 "#endif // VERTEX_SHADER\n"
2756 "#ifdef FRAGMENT_SHADER\n"
2759 "#ifdef USEDEFERREDLIGHTMAP\n"
2760 "float2 Pixel : WPOS,\n"
2762 "float4 gl_FrontColor : COLOR,\n"
2763 "float4 TexCoordBoth : TEXCOORD0,\n"
2764 "#ifdef USELIGHTMAP\n"
2765 "float2 TexCoordLightmap : TEXCOORD1,\n"
2767 "#ifdef USEEYEVECTOR\n"
2768 "float3 EyeVector : TEXCOORD2,\n"
2770 "#ifdef USEREFLECTION\n"
2771 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2774 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2776 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2777 "float3 LightVector : TEXCOORD5,\n"
2779 "#ifdef MODE_LIGHTSOURCE\n"
2780 "float3 CubeVector : TEXCOORD3,\n"
2782 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2783 "float4 ModelViewPosition : TEXCOORD0,\n"
2785 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2786 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2787 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2788 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2790 "#ifdef USESHADOWMAPORTHO\n"
2791 "float3 ShadowMapTC : TEXCOORD8\n"
2794 "uniform sampler2D Texture_Normal,\n"
2795 "uniform sampler2D Texture_Color,\n"
2796 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2797 "uniform sampler2D Texture_Gloss,\n"
2800 "uniform sampler2D Texture_Glow,\n"
2802 "#ifdef USEVERTEXTEXTUREBLEND\n"
2803 "uniform sampler2D Texture_SecondaryNormal,\n"
2804 "uniform sampler2D Texture_SecondaryColor,\n"
2805 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2806 "uniform sampler2D Texture_SecondaryGloss,\n"
2809 "uniform sampler2D Texture_SecondaryGlow,\n"
2812 "#ifdef USECOLORMAPPING\n"
2813 "uniform sampler2D Texture_Pants,\n"
2814 "uniform sampler2D Texture_Shirt,\n"
2817 "uniform sampler2D Texture_FogMask,\n"
2819 "#ifdef USELIGHTMAP\n"
2820 "uniform sampler2D Texture_Lightmap,\n"
2822 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2823 "uniform sampler2D Texture_Deluxemap,\n"
2825 "#ifdef USEREFLECTION\n"
2826 "uniform sampler2D Texture_Reflection,\n"
2829 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2830 "uniform sampler2D Texture_ScreenDepth,\n"
2831 "uniform sampler2D Texture_ScreenNormalMap,\n"
2833 "#ifdef USEDEFERREDLIGHTMAP\n"
2834 "uniform sampler2D Texture_ScreenDiffuse,\n"
2835 "uniform sampler2D Texture_ScreenSpecular,\n"
2838 "#ifdef USECOLORMAPPING\n"
2839 "uniform half3 Color_Pants,\n"
2840 "uniform half3 Color_Shirt,\n"
2843 "uniform float3 FogColor,\n"
2844 "uniform float FogRangeRecip,\n"
2845 "uniform float FogPlaneViewDist,\n"
2846 "uniform float FogHeightFade,\n"
2849 "#ifdef USEOFFSETMAPPING\n"
2850 "uniform float OffsetMapping_Scale,\n"
2853 "#ifdef USEDEFERREDLIGHTMAP\n"
2854 "uniform half2 PixelToScreenTexCoord,\n"
2855 "uniform half3 DeferredMod_Diffuse,\n"
2856 "uniform half3 DeferredMod_Specular,\n"
2858 "uniform half3 Color_Ambient,\n"
2859 "uniform half3 Color_Diffuse,\n"
2860 "uniform half3 Color_Specular,\n"
2861 "uniform half SpecularPower,\n"
2863 "uniform half3 Color_Glow,\n"
2865 "uniform half Alpha,\n"
2866 "#ifdef USEREFLECTION\n"
2867 "uniform float4 DistortScaleRefractReflect,\n"
2868 "uniform float4 ScreenScaleRefractReflect,\n"
2869 "uniform float4 ScreenCenterRefractReflect,\n"
2870 "uniform half4 ReflectColor,\n"
2872 "#ifdef USEREFLECTCUBE\n"
2873 "uniform float4x4 ModelToReflectCube,\n"
2874 "uniform sampler2D Texture_ReflectMask,\n"
2875 "uniform samplerCUBE Texture_ReflectCube,\n"
2877 "#ifdef MODE_LIGHTDIRECTION\n"
2878 "uniform half3 LightColor,\n"
2880 "#ifdef MODE_LIGHTSOURCE\n"
2881 "uniform half3 LightColor,\n"
2884 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2885 "uniform sampler2D Texture_Attenuation,\n"
2886 "uniform samplerCUBE Texture_Cube,\n"
2889 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2891 "#ifdef USESHADOWMAPRECT\n"
2892 "# ifdef USESHADOWSAMPLER\n"
2893 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2895 "uniform samplerRECT Texture_ShadowMapRect,\n"
2899 "#ifdef USESHADOWMAP2D\n"
2900 "# ifdef USESHADOWSAMPLER\n"
2901 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2903 "uniform sampler2D Texture_ShadowMap2D,\n"
2907 "#ifdef USESHADOWMAPVSDCT\n"
2908 "uniform samplerCUBE Texture_CubeProjection,\n"
2911 "#ifdef USESHADOWMAPCUBE\n"
2912 "# ifdef USESHADOWSAMPLER\n"
2913 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2915 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2919 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2920 "uniform float2 ShadowMap_TextureScale,\n"
2921 "uniform float4 ShadowMap_Parameters,\n"
2923 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2925 "out float4 gl_FragColor : COLOR\n"
2928 " float2 TexCoord = TexCoordBoth.xy;\n"
2929 "#ifdef USEVERTEXTEXTUREBLEND\n"
2930 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2932 "#ifdef USEOFFSETMAPPING\n"
2933 " // apply offsetmapping\n"
2934 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2935 "#define TexCoord TexCoordOffset\n"
2938 " // combine the diffuse textures (base, pants, shirt)\n"
2939 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2940 "#ifdef USEALPHAKILL\n"
2941 " if (color.a < 0.5)\n"
2944 " color.a *= Alpha;\n"
2945 "#ifdef USECOLORMAPPING\n"
2946 " color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2948 "#ifdef USEVERTEXTEXTUREBLEND\n"
2949 " float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2950 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2951 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2952 " color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2954 " //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2957 " // get the surface normal\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 " half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2961 " half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2964 " // get the material colors\n"
2965 " half3 diffusetex = color.rgb;\n"
2966 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2967 "# ifdef USEVERTEXTEXTUREBLEND\n"
2968 " half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2970 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2974 "#ifdef USEREFLECTCUBE\n"
2975 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2976 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2977 " vec3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2978 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2984 "#ifdef MODE_LIGHTSOURCE\n"
2985 " // light source\n"
2986 "#ifdef USEDIFFUSE\n"
2987 " half3 lightnormal = half3(normalize(LightVector));\n"
2988 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2989 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2990 "#ifdef USESPECULAR\n"
2991 "#ifdef USEEXACTSPECULARMATH\n"
2992 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
2994 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2995 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
2997 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3000 " color.rgb = diffusetex * Color_Ambient;\n"
3002 " color.rgb *= LightColor;\n"
3003 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3004 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3005 " color.rgb *= ShadowMapCompare(CubeVector,\n"
3006 "# if defined(USESHADOWMAP2D)\n"
3007 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3009 "# if defined(USESHADOWMAPRECT)\n"
3010 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3012 "# if defined(USESHADOWMAPCUBE)\n"
3013 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3016 "#ifdef USESHADOWMAPVSDCT\n"
3017 ", Texture_CubeProjection\n"
3022 "# ifdef USECUBEFILTER\n"
3023 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3025 "#endif // MODE_LIGHTSOURCE\n"
3030 "#ifdef MODE_LIGHTDIRECTION\n"
3032 "#ifdef USEDIFFUSE\n"
3033 " half3 lightnormal = half3(normalize(LightVector));\n"
3035 "#define lightcolor LightColor\n"
3036 "#endif // MODE_LIGHTDIRECTION\n"
3037 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3039 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3040 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3041 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3042 " // convert modelspace light vector to tangentspace\n"
3043 " half3 lightnormal;\n"
3044 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3045 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3046 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3047 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3048 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3049 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3050 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3051 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3052 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3053 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3054 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3055 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3056 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3057 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3058 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3060 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3061 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3062 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3068 "#ifdef MODE_LIGHTMAP\n"
3069 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3070 "#endif // MODE_LIGHTMAP\n"
3071 "#ifdef MODE_VERTEXCOLOR\n"
3072 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3073 "#endif // MODE_VERTEXCOLOR\n"
3074 "#ifdef MODE_FLATCOLOR\n"
3075 " color.rgb = diffusetex * Color_Ambient;\n"
3076 "#endif // MODE_FLATCOLOR\n"
3082 "# ifdef USEDIFFUSE\n"
3083 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3084 "# ifdef USESPECULAR\n"
3085 "# ifdef USEEXACTSPECULARMATH\n"
3086 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3088 " half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3089 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3091 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3093 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3096 " color.rgb = diffusetex * Color_Ambient;\n"
3100 "#ifdef USESHADOWMAPORTHO\n"
3101 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3102 "# if defined(USESHADOWMAP2D)\n"
3103 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3105 "# if defined(USESHADOWMAPRECT)\n"
3106 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3111 "#ifdef USEDEFERREDLIGHTMAP\n"
3112 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3113 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3114 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3118 "#ifdef USEVERTEXTEXTUREBLEND\n"
3119 " color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3121 " color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3126 "#ifdef MODE_LIGHTSOURCE\n"
3127 " color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3129 " color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3133 " // 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"
3134 "#ifdef USEREFLECTION\n"
3135 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3136 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3137 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3138 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3139 " // FIXME temporary hack to detect the case that the reflection\n"
3140 " // gets blackened at edges due to leaving the area that contains actual\n"
3142 " // Remove this 'ack once we have a better way to stop this thing from\n"
3144 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3145 " 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 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3149 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3152 " gl_FragColor = float4(color);\n"
3154 "#endif // FRAGMENT_SHADER\n"
3156 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3157 "#endif // !MODE_DEFERREDGEOMETRY\n"
3158 "#endif // !MODE_WATER\n"
3159 "#endif // !MODE_REFRACTION\n"
3160 "#endif // !MODE_BLOOMBLUR\n"
3161 "#endif // !MODE_GENERIC\n"
3162 "#endif // !MODE_POSTPROCESS\n"
3163 "#endif // !MODE_SHOWDEPTH\n"
3164 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3167 char *glslshaderstring = NULL;
3168 char *cgshaderstring = NULL;
3170 //=======================================================================================================================================================
3172 typedef struct shaderpermutationinfo_s
3174 const char *pretext;
3177 shaderpermutationinfo_t;
3179 typedef struct shadermodeinfo_s
3181 const char *vertexfilename;
3182 const char *geometryfilename;
3183 const char *fragmentfilename;
3184 const char *pretext;
3189 typedef enum shaderpermutation_e
3191 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3192 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3193 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3194 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3195 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3196 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3197 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3198 SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3199 SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3200 SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3201 SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3202 SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3203 SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3204 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3205 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3206 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3207 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3208 SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3209 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3210 SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3211 SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3212 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3213 SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3214 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3215 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3216 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3217 SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3218 SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3219 SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3220 SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3222 shaderpermutation_t;
3224 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3225 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3227 {"#define USEDIFFUSE\n", " diffuse"},
3228 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3229 {"#define USEVIEWTINT\n", " viewtint"},
3230 {"#define USECOLORMAPPING\n", " colormapping"},
3231 {"#define USESATURATION\n", " saturation"},
3232 {"#define USEFOGINSIDE\n", " foginside"},
3233 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3234 {"#define USEGAMMARAMPS\n", " gammaramps"},
3235 {"#define USECUBEFILTER\n", " cubefilter"},
3236 {"#define USEGLOW\n", " glow"},
3237 {"#define USEBLOOM\n", " bloom"},
3238 {"#define USESPECULAR\n", " specular"},
3239 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3240 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3241 {"#define USEREFLECTION\n", " reflection"},
3242 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3243 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3244 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3245 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3246 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3247 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3248 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3249 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3250 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3251 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3252 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3253 {"#define USEALPHAKILL\n", " alphakill"},
3254 {"#define USEREFLECTCUBE\n", " reflectcube"},
3257 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3258 typedef enum shadermode_e
3260 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3261 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3262 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3263 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3264 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3265 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3266 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3267 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3268 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3269 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3270 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3271 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3272 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3273 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3274 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3279 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3280 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3282 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3283 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3284 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3285 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3286 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3287 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3288 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3289 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3290 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3291 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3292 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3293 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3294 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3295 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3296 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3300 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3302 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3303 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3304 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3305 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3306 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3307 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3308 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3309 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3310 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3311 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3312 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3313 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3314 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3315 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3316 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3320 struct r_glsl_permutation_s;
3321 typedef struct r_glsl_permutation_s
3323 /// hash lookup data
3324 struct r_glsl_permutation_s *hashnext;
3326 unsigned int permutation;
3328 /// indicates if we have tried compiling this permutation already
3330 /// 0 if compilation failed
3332 /// locations of detected uniforms in program object, or -1 if not found
3333 int loc_Texture_First;
3334 int loc_Texture_Second;
3335 int loc_Texture_GammaRamps;
3336 int loc_Texture_Normal;
3337 int loc_Texture_Color;
3338 int loc_Texture_Gloss;
3339 int loc_Texture_Glow;
3340 int loc_Texture_SecondaryNormal;
3341 int loc_Texture_SecondaryColor;
3342 int loc_Texture_SecondaryGloss;
3343 int loc_Texture_SecondaryGlow;
3344 int loc_Texture_Pants;
3345 int loc_Texture_Shirt;
3346 int loc_Texture_FogMask;
3347 int loc_Texture_Lightmap;
3348 int loc_Texture_Deluxemap;
3349 int loc_Texture_Attenuation;
3350 int loc_Texture_Cube;
3351 int loc_Texture_Refraction;
3352 int loc_Texture_Reflection;
3353 int loc_Texture_ShadowMapRect;
3354 int loc_Texture_ShadowMapCube;
3355 int loc_Texture_ShadowMap2D;
3356 int loc_Texture_CubeProjection;
3357 int loc_Texture_ScreenDepth;
3358 int loc_Texture_ScreenNormalMap;
3359 int loc_Texture_ScreenDiffuse;
3360 int loc_Texture_ScreenSpecular;
3361 int loc_Texture_ReflectMask;
3362 int loc_Texture_ReflectCube;
3364 int loc_BloomBlur_Parameters;
3366 int loc_Color_Ambient;
3367 int loc_Color_Diffuse;
3368 int loc_Color_Specular;
3370 int loc_Color_Pants;
3371 int loc_Color_Shirt;
3372 int loc_DeferredColor_Ambient;
3373 int loc_DeferredColor_Diffuse;
3374 int loc_DeferredColor_Specular;
3375 int loc_DeferredMod_Diffuse;
3376 int loc_DeferredMod_Specular;
3377 int loc_DistortScaleRefractReflect;
3378 int loc_EyePosition;
3380 int loc_FogHeightFade;
3382 int loc_FogPlaneViewDist;
3383 int loc_FogRangeRecip;
3386 int loc_LightPosition;
3387 int loc_OffsetMapping_Scale;
3389 int loc_ReflectColor;
3390 int loc_ReflectFactor;
3391 int loc_ReflectOffset;
3392 int loc_RefractColor;
3394 int loc_ScreenCenterRefractReflect;
3395 int loc_ScreenScaleRefractReflect;
3396 int loc_ScreenToDepth;
3397 int loc_ShadowMap_Parameters;
3398 int loc_ShadowMap_TextureScale;
3399 int loc_SpecularPower;
3404 int loc_ViewTintColor;
3405 int loc_ViewToLight;
3406 int loc_ModelToLight;
3408 int loc_BackgroundTexMatrix;
3409 int loc_ModelViewProjectionMatrix;
3410 int loc_ModelViewMatrix;
3411 int loc_PixelToScreenTexCoord;
3412 int loc_ModelToReflectCube;
3413 int loc_ShadowMapMatrix;
3415 r_glsl_permutation_t;
3417 #define SHADERPERMUTATION_HASHSIZE 256
3419 /// information about each possible shader permutation
3420 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3421 /// currently selected permutation
3422 r_glsl_permutation_t *r_glsl_permutation;
3423 /// storage for permutations linked in the hash table
3424 memexpandablearray_t r_glsl_permutationarray;
3426 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3428 //unsigned int hashdepth = 0;
3429 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3430 r_glsl_permutation_t *p;
3431 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3433 if (p->mode == mode && p->permutation == permutation)
3435 //if (hashdepth > 10)
3436 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3441 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3443 p->permutation = permutation;
3444 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3445 r_glsl_permutationhash[mode][hashindex] = p;
3446 //if (hashdepth > 10)
3447 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3451 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3454 if (!filename || !filename[0])
3456 if (!strcmp(filename, "glsl/default.glsl"))
3458 if (!glslshaderstring)
3460 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3461 if (glslshaderstring)
3462 Con_DPrintf("Loading shaders from file %s...\n", filename);
3464 glslshaderstring = (char *)builtinshaderstring;
3466 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3467 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3468 return shaderstring;
3470 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3473 if (printfromdisknotice)
3474 Con_DPrintf("from disk %s... ", filename);
3475 return shaderstring;
3477 return shaderstring;
3480 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3483 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3484 int vertstrings_count = 0;
3485 int geomstrings_count = 0;
3486 int fragstrings_count = 0;
3487 char *vertexstring, *geometrystring, *fragmentstring;
3488 const char *vertstrings_list[32+3];
3489 const char *geomstrings_list[32+3];
3490 const char *fragstrings_list[32+3];
3491 char permutationname[256];
3498 permutationname[0] = 0;
3499 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3500 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3501 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3503 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3505 // the first pretext is which type of shader to compile as
3506 // (later these will all be bound together as a program object)
3507 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3508 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3509 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3511 // the second pretext is the mode (for example a light source)
3512 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3513 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3514 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3515 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3517 // now add all the permutation pretexts
3518 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3520 if (permutation & (1<<i))
3522 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3523 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3524 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3525 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3529 // keep line numbers correct
3530 vertstrings_list[vertstrings_count++] = "\n";
3531 geomstrings_list[geomstrings_count++] = "\n";
3532 fragstrings_list[fragstrings_count++] = "\n";
3536 // now append the shader text itself
3537 vertstrings_list[vertstrings_count++] = vertexstring;
3538 geomstrings_list[geomstrings_count++] = geometrystring;
3539 fragstrings_list[fragstrings_count++] = fragmentstring;
3541 // if any sources were NULL, clear the respective list
3543 vertstrings_count = 0;
3544 if (!geometrystring)
3545 geomstrings_count = 0;
3546 if (!fragmentstring)
3547 fragstrings_count = 0;
3549 // compile the shader program
3550 if (vertstrings_count + geomstrings_count + fragstrings_count)
3551 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3555 qglUseProgramObjectARB(p->program);CHECKGLERROR
3556 // look up all the uniform variable names we care about, so we don't
3557 // have to look them up every time we set them
3559 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3560 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3561 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3562 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3563 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3564 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3565 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3566 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3567 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3568 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3569 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3570 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3571 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3572 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3573 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3574 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3575 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3576 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3577 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3578 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3579 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3580 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3581 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3582 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3583 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3584 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3585 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3586 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3587 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3588 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3589 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3590 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3591 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3592 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3593 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3594 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3595 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3596 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3597 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3598 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3599 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3600 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3601 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3602 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3603 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3604 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3605 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3606 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3607 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3608 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3609 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3610 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3611 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3612 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3613 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3614 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3615 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3616 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3617 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3618 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3619 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3620 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3621 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3622 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3623 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3624 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3625 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3626 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3627 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3628 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3629 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3630 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3631 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3632 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3633 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3634 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3635 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3636 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3637 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3638 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3639 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3640 // initialize the samplers to refer to the texture units we use
3641 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3642 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3643 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3644 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3645 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3646 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3647 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3648 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3649 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3650 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3651 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3652 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3653 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3654 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3655 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3656 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3657 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3658 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3659 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3660 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3661 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3662 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3663 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3664 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3665 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3666 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3667 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3668 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3669 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3670 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3672 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3675 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3679 Mem_Free(vertexstring);
3681 Mem_Free(geometrystring);
3683 Mem_Free(fragmentstring);
3686 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3688 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3689 if (r_glsl_permutation != perm)
3691 r_glsl_permutation = perm;
3692 if (!r_glsl_permutation->program)
3694 if (!r_glsl_permutation->compiled)
3695 R_GLSL_CompilePermutation(perm, mode, permutation);
3696 if (!r_glsl_permutation->program)
3698 // remove features until we find a valid permutation
3700 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3702 // reduce i more quickly whenever it would not remove any bits
3703 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3704 if (!(permutation & j))
3707 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3708 if (!r_glsl_permutation->compiled)
3709 R_GLSL_CompilePermutation(perm, mode, permutation);
3710 if (r_glsl_permutation->program)
3713 if (i >= SHADERPERMUTATION_COUNT)
3715 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3716 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3717 qglUseProgramObjectARB(0);CHECKGLERROR
3718 return; // no bit left to clear, entire mode is broken
3723 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3725 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3726 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3727 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3731 #include <Cg/cgGL.h>
3732 struct r_cg_permutation_s;
3733 typedef struct r_cg_permutation_s
3735 /// hash lookup data
3736 struct r_cg_permutation_s *hashnext;
3738 unsigned int permutation;
3740 /// indicates if we have tried compiling this permutation already
3742 /// 0 if compilation failed
3745 /// locations of detected parameters in programs, or NULL if not found
3746 CGparameter vp_EyePosition;
3747 CGparameter vp_FogPlane;
3748 CGparameter vp_LightDir;
3749 CGparameter vp_LightPosition;
3750 CGparameter vp_ModelToLight;
3751 CGparameter vp_TexMatrix;
3752 CGparameter vp_BackgroundTexMatrix;
3753 CGparameter vp_ModelViewProjectionMatrix;
3754 CGparameter vp_ModelViewMatrix;
3755 CGparameter vp_ShadowMapMatrix;
3757 CGparameter fp_Texture_First;
3758 CGparameter fp_Texture_Second;
3759 CGparameter fp_Texture_GammaRamps;
3760 CGparameter fp_Texture_Normal;
3761 CGparameter fp_Texture_Color;
3762 CGparameter fp_Texture_Gloss;
3763 CGparameter fp_Texture_Glow;
3764 CGparameter fp_Texture_SecondaryNormal;
3765 CGparameter fp_Texture_SecondaryColor;
3766 CGparameter fp_Texture_SecondaryGloss;
3767 CGparameter fp_Texture_SecondaryGlow;
3768 CGparameter fp_Texture_Pants;
3769 CGparameter fp_Texture_Shirt;
3770 CGparameter fp_Texture_FogMask;
3771 CGparameter fp_Texture_Lightmap;
3772 CGparameter fp_Texture_Deluxemap;
3773 CGparameter fp_Texture_Attenuation;
3774 CGparameter fp_Texture_Cube;
3775 CGparameter fp_Texture_Refraction;
3776 CGparameter fp_Texture_Reflection;
3777 CGparameter fp_Texture_ShadowMapRect;
3778 CGparameter fp_Texture_ShadowMapCube;
3779 CGparameter fp_Texture_ShadowMap2D;
3780 CGparameter fp_Texture_CubeProjection;
3781 CGparameter fp_Texture_ScreenDepth;
3782 CGparameter fp_Texture_ScreenNormalMap;
3783 CGparameter fp_Texture_ScreenDiffuse;
3784 CGparameter fp_Texture_ScreenSpecular;
3785 CGparameter fp_Texture_ReflectMask;
3786 CGparameter fp_Texture_ReflectCube;
3787 CGparameter fp_Alpha;
3788 CGparameter fp_BloomBlur_Parameters;
3789 CGparameter fp_ClientTime;
3790 CGparameter fp_Color_Ambient;
3791 CGparameter fp_Color_Diffuse;
3792 CGparameter fp_Color_Specular;
3793 CGparameter fp_Color_Glow;
3794 CGparameter fp_Color_Pants;
3795 CGparameter fp_Color_Shirt;
3796 CGparameter fp_DeferredColor_Ambient;
3797 CGparameter fp_DeferredColor_Diffuse;
3798 CGparameter fp_DeferredColor_Specular;
3799 CGparameter fp_DeferredMod_Diffuse;
3800 CGparameter fp_DeferredMod_Specular;
3801 CGparameter fp_DistortScaleRefractReflect;
3802 CGparameter fp_EyePosition;
3803 CGparameter fp_FogColor;
3804 CGparameter fp_FogHeightFade;
3805 CGparameter fp_FogPlane;
3806 CGparameter fp_FogPlaneViewDist;
3807 CGparameter fp_FogRangeRecip;
3808 CGparameter fp_LightColor;
3809 CGparameter fp_LightDir;
3810 CGparameter fp_LightPosition;
3811 CGparameter fp_OffsetMapping_Scale;
3812 CGparameter fp_PixelSize;
3813 CGparameter fp_ReflectColor;
3814 CGparameter fp_ReflectFactor;
3815 CGparameter fp_ReflectOffset;
3816 CGparameter fp_RefractColor;
3817 CGparameter fp_Saturation;
3818 CGparameter fp_ScreenCenterRefractReflect;
3819 CGparameter fp_ScreenScaleRefractReflect;
3820 CGparameter fp_ScreenToDepth;
3821 CGparameter fp_ShadowMap_Parameters;
3822 CGparameter fp_ShadowMap_TextureScale;
3823 CGparameter fp_SpecularPower;
3824 CGparameter fp_UserVec1;
3825 CGparameter fp_UserVec2;
3826 CGparameter fp_UserVec3;
3827 CGparameter fp_UserVec4;
3828 CGparameter fp_ViewTintColor;
3829 CGparameter fp_ViewToLight;
3830 CGparameter fp_PixelToScreenTexCoord;
3831 CGparameter fp_ModelToReflectCube;
3835 /// information about each possible shader permutation
3836 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3837 /// currently selected permutation
3838 r_cg_permutation_t *r_cg_permutation;
3839 /// storage for permutations linked in the hash table
3840 memexpandablearray_t r_cg_permutationarray;
3842 #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));}}
3844 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3846 //unsigned int hashdepth = 0;
3847 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3848 r_cg_permutation_t *p;
3849 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3851 if (p->mode == mode && p->permutation == permutation)
3853 //if (hashdepth > 10)
3854 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3859 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3861 p->permutation = permutation;
3862 p->hashnext = r_cg_permutationhash[mode][hashindex];
3863 r_cg_permutationhash[mode][hashindex] = p;
3864 //if (hashdepth > 10)
3865 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3869 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3872 if (!filename || !filename[0])
3874 if (!strcmp(filename, "cg/default.cg"))
3876 if (!cgshaderstring)
3878 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3880 Con_DPrintf("Loading shaders from file %s...\n", filename);
3882 cgshaderstring = (char *)builtincgshaderstring;
3884 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3885 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3886 return shaderstring;
3888 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3891 if (printfromdisknotice)
3892 Con_DPrintf("from disk %s... ", filename);
3893 return shaderstring;
3895 return shaderstring;
3898 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3900 // TODO: load or create .fp and .vp shader files
3903 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3906 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3907 int vertstrings_count = 0, vertstring_length = 0;
3908 int geomstrings_count = 0, geomstring_length = 0;
3909 int fragstrings_count = 0, fragstring_length = 0;
3911 char *vertexstring, *geometrystring, *fragmentstring;
3912 char *vertstring, *geomstring, *fragstring;
3913 const char *vertstrings_list[32+3];
3914 const char *geomstrings_list[32+3];
3915 const char *fragstrings_list[32+3];
3916 char permutationname[256];
3917 char cachename[256];
3918 CGprofile vertexProfile;
3919 CGprofile fragmentProfile;
3927 permutationname[0] = 0;
3929 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
3930 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3931 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3933 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3934 strlcat(cachename, "cg/", sizeof(cachename));
3936 // the first pretext is which type of shader to compile as
3937 // (later these will all be bound together as a program object)
3938 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3939 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3940 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3942 // the second pretext is the mode (for example a light source)
3943 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3944 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3945 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3946 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3947 strlcat(cachename, modeinfo->name, sizeof(cachename));
3949 // now add all the permutation pretexts
3950 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3952 if (permutation & (1<<i))
3954 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3955 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3956 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3957 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3958 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3962 // keep line numbers correct
3963 vertstrings_list[vertstrings_count++] = "\n";
3964 geomstrings_list[geomstrings_count++] = "\n";
3965 fragstrings_list[fragstrings_count++] = "\n";
3969 // replace spaces in the cachename with _ characters
3970 for (i = 0;cachename[i];i++)
3971 if (cachename[i] == ' ')
3974 // now append the shader text itself
3975 vertstrings_list[vertstrings_count++] = vertexstring;
3976 geomstrings_list[geomstrings_count++] = geometrystring;
3977 fragstrings_list[fragstrings_count++] = fragmentstring;
3979 // if any sources were NULL, clear the respective list
3981 vertstrings_count = 0;
3982 if (!geometrystring)
3983 geomstrings_count = 0;
3984 if (!fragmentstring)
3985 fragstrings_count = 0;
3987 vertstring_length = 0;
3988 for (i = 0;i < vertstrings_count;i++)
3989 vertstring_length += strlen(vertstrings_list[i]);
3990 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3991 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3992 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3994 geomstring_length = 0;
3995 for (i = 0;i < geomstrings_count;i++)
3996 geomstring_length += strlen(geomstrings_list[i]);
3997 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3998 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3999 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4001 fragstring_length = 0;
4002 for (i = 0;i < fragstrings_count;i++)
4003 fragstring_length += strlen(fragstrings_list[i]);
4004 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4005 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4006 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4010 //vertexProfile = CG_PROFILE_ARBVP1;
4011 //fragmentProfile = CG_PROFILE_ARBFP1;
4012 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4013 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4014 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4015 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4016 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4019 // try to load the cached shader, or generate one
4020 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4022 // if caching failed, do a dynamic compile for now
4024 if (vertstring[0] && !p->vprogram)
4025 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4027 if (fragstring[0] && !p->fprogram)
4028 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4031 // look up all the uniform variable names we care about, so we don't
4032 // have to look them up every time we set them
4036 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4037 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4038 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4039 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4040 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4041 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4042 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4043 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4044 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4045 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4046 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4047 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4053 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4054 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4055 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4056 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4057 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4058 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4059 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4060 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4061 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4062 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4063 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4064 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4065 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4066 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4067 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4068 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4069 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4070 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4071 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4072 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4073 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4074 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4075 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4076 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4077 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4078 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4079 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4080 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4081 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4082 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4083 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4084 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4085 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4086 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4087 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4088 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4089 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4090 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4091 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4092 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4093 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4094 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4095 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4096 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4097 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4098 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4099 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4100 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4101 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4102 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4103 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4104 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4105 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4106 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4107 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4108 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4109 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4110 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4111 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4112 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4113 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4114 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4115 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4116 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4117 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4118 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4119 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4120 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4121 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4122 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4123 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4124 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4125 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4126 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4127 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4128 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4129 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4133 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4134 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4136 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4140 Mem_Free(vertstring);
4142 Mem_Free(geomstring);
4144 Mem_Free(fragstring);
4146 Mem_Free(vertexstring);
4148 Mem_Free(geometrystring);
4150 Mem_Free(fragmentstring);
4153 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4155 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4158 if (r_cg_permutation != perm)
4160 r_cg_permutation = perm;
4161 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4163 if (!r_cg_permutation->compiled)
4164 R_CG_CompilePermutation(perm, mode, permutation);
4165 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4167 // remove features until we find a valid permutation
4169 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4171 // reduce i more quickly whenever it would not remove any bits
4172 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4173 if (!(permutation & j))
4176 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4177 if (!r_cg_permutation->compiled)
4178 R_CG_CompilePermutation(perm, mode, permutation);
4179 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4182 if (i >= SHADERPERMUTATION_COUNT)
4184 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4185 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4186 return; // no bit left to clear, entire mode is broken
4192 if (r_cg_permutation->vprogram)
4194 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4195 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4196 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4200 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4201 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4203 if (r_cg_permutation->fprogram)
4205 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4206 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4207 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4211 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4212 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4216 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4217 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4218 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4221 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4223 cgGLSetTextureParameter(param, R_GetTexture(tex));
4224 cgGLEnableTextureParameter(param);
4228 void R_GLSL_Restart_f(void)
4230 unsigned int i, limit;
4231 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4232 Mem_Free(glslshaderstring);
4233 glslshaderstring = NULL;
4234 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4235 Mem_Free(cgshaderstring);
4236 cgshaderstring = NULL;
4237 switch(vid.renderpath)
4239 case RENDERPATH_GL20:
4241 r_glsl_permutation_t *p;
4242 r_glsl_permutation = NULL;
4243 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4244 for (i = 0;i < limit;i++)
4246 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4248 GL_Backend_FreeProgram(p->program);
4249 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4252 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4255 case RENDERPATH_CGGL:
4258 r_cg_permutation_t *p;
4259 r_cg_permutation = NULL;
4260 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4261 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4262 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4263 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4264 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4265 for (i = 0;i < limit;i++)
4267 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4270 cgDestroyProgram(p->vprogram);
4272 cgDestroyProgram(p->fprogram);
4273 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4276 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4280 case RENDERPATH_GL13:
4281 case RENDERPATH_GL11:
4286 void R_GLSL_DumpShader_f(void)
4291 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4294 FS_Print(file, "/* The engine may define the following macros:\n");
4295 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4296 for (i = 0;i < SHADERMODE_COUNT;i++)
4297 FS_Print(file, glslshadermodeinfo[i].pretext);
4298 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4299 FS_Print(file, shaderpermutationinfo[i].pretext);
4300 FS_Print(file, "*/\n");
4301 FS_Print(file, builtinshaderstring);
4303 Con_Printf("glsl/default.glsl written\n");
4306 Con_Printf("failed to write to glsl/default.glsl\n");
4309 file = FS_OpenRealFile("cg/default.cg", "w", false);
4312 FS_Print(file, "/* The engine may define the following macros:\n");
4313 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4314 for (i = 0;i < SHADERMODE_COUNT;i++)
4315 FS_Print(file, cgshadermodeinfo[i].pretext);
4316 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4317 FS_Print(file, shaderpermutationinfo[i].pretext);
4318 FS_Print(file, "*/\n");
4319 FS_Print(file, builtincgshaderstring);
4321 Con_Printf("cg/default.cg written\n");
4324 Con_Printf("failed to write to cg/default.cg\n");
4328 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4331 texturemode = GL_MODULATE;
4332 switch (vid.renderpath)
4334 case RENDERPATH_GL20:
4335 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))));
4336 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4337 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4339 case RENDERPATH_CGGL:
4342 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))));
4343 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4344 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4347 case RENDERPATH_GL13:
4348 R_Mesh_TexBind(0, first );
4349 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4350 R_Mesh_TexBind(1, second);
4352 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4354 case RENDERPATH_GL11:
4355 R_Mesh_TexBind(0, first );
4360 void R_SetupShader_DepthOrShadow(void)
4362 switch (vid.renderpath)
4364 case RENDERPATH_GL20:
4365 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4367 case RENDERPATH_CGGL:
4369 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4372 case RENDERPATH_GL13:
4373 R_Mesh_TexBind(0, 0);
4374 R_Mesh_TexBind(1, 0);
4376 case RENDERPATH_GL11:
4377 R_Mesh_TexBind(0, 0);
4382 void R_SetupShader_ShowDepth(void)
4384 switch (vid.renderpath)
4386 case RENDERPATH_GL20:
4387 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4389 case RENDERPATH_CGGL:
4391 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4394 case RENDERPATH_GL13:
4396 case RENDERPATH_GL11:
4401 extern qboolean r_shadow_usingdeferredprepass;
4402 extern cvar_t r_shadow_deferred_8bitrange;
4403 extern rtexture_t *r_shadow_attenuationgradienttexture;
4404 extern rtexture_t *r_shadow_attenuation2dtexture;
4405 extern rtexture_t *r_shadow_attenuation3dtexture;
4406 extern qboolean r_shadow_usingshadowmaprect;
4407 extern qboolean r_shadow_usingshadowmapcube;
4408 extern qboolean r_shadow_usingshadowmap2d;
4409 extern qboolean r_shadow_usingshadowmaportho;
4410 extern float r_shadow_shadowmap_texturescale[2];
4411 extern float r_shadow_shadowmap_parameters[4];
4412 extern qboolean r_shadow_shadowmapvsdct;
4413 extern qboolean r_shadow_shadowmapsampler;
4414 extern int r_shadow_shadowmappcf;
4415 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4416 extern rtexture_t *r_shadow_shadowmap2dtexture;
4417 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4418 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4419 extern matrix4x4_t r_shadow_shadowmapmatrix;
4420 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4421 extern int r_shadow_prepass_width;
4422 extern int r_shadow_prepass_height;
4423 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4424 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4425 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4426 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4427 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4429 // select a permutation of the lighting shader appropriate to this
4430 // combination of texture, entity, light source, and fogging, only use the
4431 // minimum features necessary to avoid wasting rendering time in the
4432 // fragment shader on features that are not being used
4433 unsigned int permutation = 0;
4434 unsigned int mode = 0;
4436 if (rsurfacepass == RSURFPASS_BACKGROUND)
4438 // distorted background
4439 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4440 mode = SHADERMODE_WATER;
4442 mode = SHADERMODE_REFRACTION;
4443 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4444 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4445 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4446 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4447 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4448 R_Mesh_ColorPointer(NULL, 0, 0);
4449 GL_AlphaTest(false);
4450 GL_BlendFunc(GL_ONE, GL_ZERO);
4452 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4454 if (r_glsl_offsetmapping.integer)
4456 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4457 if (r_glsl_offsetmapping_reliefmapping.integer)
4458 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4461 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4462 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4463 permutation |= SHADERPERMUTATION_ALPHAKILL;
4464 // normalmap (deferred prepass), may use alpha test on diffuse
4465 mode = SHADERMODE_DEFERREDGEOMETRY;
4466 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4467 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4468 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4469 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4470 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4471 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4472 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4473 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4474 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4476 R_Mesh_ColorPointer(NULL, 0, 0);
4477 GL_AlphaTest(false);
4478 GL_BlendFunc(GL_ONE, GL_ZERO);
4480 else if (rsurfacepass == RSURFPASS_RTLIGHT)
4482 if (r_glsl_offsetmapping.integer)
4484 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4485 if (r_glsl_offsetmapping_reliefmapping.integer)
4486 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4488 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4489 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4491 mode = SHADERMODE_LIGHTSOURCE;
4492 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4493 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4494 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4495 permutation |= SHADERPERMUTATION_CUBEFILTER;
4496 if (diffusescale > 0)
4497 permutation |= SHADERPERMUTATION_DIFFUSE;
4498 if (specularscale > 0)
4500 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4501 if (r_shadow_glossexact.integer)
4502 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4504 if (r_refdef.fogenabled)
4505 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4506 if (rsurface.texture->colormapping)
4507 permutation |= SHADERPERMUTATION_COLORMAPPING;
4508 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4510 if (r_shadow_usingshadowmaprect)
4511 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4512 if (r_shadow_usingshadowmap2d)
4513 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4514 if (r_shadow_usingshadowmapcube)
4515 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4516 else if(r_shadow_shadowmapvsdct)
4517 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4519 if (r_shadow_shadowmapsampler)
4520 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4521 if (r_shadow_shadowmappcf > 1)
4522 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4523 else if (r_shadow_shadowmappcf)
4524 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4526 if (rsurface.texture->reflectmasktexture)
4527 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4528 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4529 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4531 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4532 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4533 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4537 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4538 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4539 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4541 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4542 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4543 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4545 R_Mesh_ColorPointer(NULL, 0, 0);
4546 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4547 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4549 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4551 if (r_glsl_offsetmapping.integer)
4553 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4554 if (r_glsl_offsetmapping_reliefmapping.integer)
4555 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4557 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4558 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4559 // unshaded geometry (fullbright or ambient model lighting)
4560 mode = SHADERMODE_FLATCOLOR;
4561 ambientscale = diffusescale = specularscale = 0;
4562 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4563 permutation |= SHADERPERMUTATION_GLOW;
4564 if (r_refdef.fogenabled)
4565 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4566 if (rsurface.texture->colormapping)
4567 permutation |= SHADERPERMUTATION_COLORMAPPING;
4568 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4570 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4571 if (r_shadow_usingshadowmaprect)
4572 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4573 if (r_shadow_usingshadowmap2d)
4574 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4576 if (r_shadow_shadowmapsampler)
4577 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4578 if (r_shadow_shadowmappcf > 1)
4579 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4580 else if (r_shadow_shadowmappcf)
4581 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4583 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4584 permutation |= SHADERPERMUTATION_REFLECTION;
4585 if (rsurface.texture->reflectmasktexture)
4586 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4587 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4588 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4590 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4591 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4592 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4596 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4597 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4598 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4600 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4601 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4602 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4604 R_Mesh_ColorPointer(NULL, 0, 0);
4605 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4606 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4608 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4610 if (r_glsl_offsetmapping.integer)
4612 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4613 if (r_glsl_offsetmapping_reliefmapping.integer)
4614 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4617 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4618 // directional model lighting
4619 mode = SHADERMODE_LIGHTDIRECTION;
4620 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4621 permutation |= SHADERPERMUTATION_GLOW;
4622 permutation |= SHADERPERMUTATION_DIFFUSE;
4623 if (specularscale > 0)
4625 permutation |= SHADERPERMUTATION_SPECULAR;
4626 if (r_shadow_glossexact.integer)
4627 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4629 if (r_refdef.fogenabled)
4630 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4631 if (rsurface.texture->colormapping)
4632 permutation |= SHADERPERMUTATION_COLORMAPPING;
4633 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4635 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4636 if (r_shadow_usingshadowmaprect)
4637 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4638 if (r_shadow_usingshadowmap2d)
4639 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4641 if (r_shadow_shadowmapsampler)
4642 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4643 if (r_shadow_shadowmappcf > 1)
4644 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4645 else if (r_shadow_shadowmappcf)
4646 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4648 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4649 permutation |= SHADERPERMUTATION_REFLECTION;
4650 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4651 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4652 if (rsurface.texture->reflectmasktexture)
4653 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4654 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4655 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4657 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4658 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4659 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4663 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4664 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4665 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4667 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4668 R_Mesh_ColorPointer(NULL, 0, 0);
4669 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4670 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4672 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4674 if (r_glsl_offsetmapping.integer)
4676 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4677 if (r_glsl_offsetmapping_reliefmapping.integer)
4678 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4680 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4681 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4682 // ambient model lighting
4683 mode = SHADERMODE_LIGHTDIRECTION;
4684 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4685 permutation |= SHADERPERMUTATION_GLOW;
4686 if (r_refdef.fogenabled)
4687 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4688 if (rsurface.texture->colormapping)
4689 permutation |= SHADERPERMUTATION_COLORMAPPING;
4690 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4692 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4693 if (r_shadow_usingshadowmaprect)
4694 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4695 if (r_shadow_usingshadowmap2d)
4696 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4698 if (r_shadow_shadowmapsampler)
4699 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4700 if (r_shadow_shadowmappcf > 1)
4701 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4702 else if (r_shadow_shadowmappcf)
4703 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4705 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4706 permutation |= SHADERPERMUTATION_REFLECTION;
4707 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4708 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4709 if (rsurface.texture->reflectmasktexture)
4710 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4711 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4712 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4714 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4715 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4716 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4720 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4721 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4722 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4724 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4725 R_Mesh_ColorPointer(NULL, 0, 0);
4726 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4727 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4731 if (r_glsl_offsetmapping.integer)
4733 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4734 if (r_glsl_offsetmapping_reliefmapping.integer)
4735 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4737 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4738 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4740 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4741 permutation |= SHADERPERMUTATION_GLOW;
4742 if (r_refdef.fogenabled)
4743 permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4744 if (rsurface.texture->colormapping)
4745 permutation |= SHADERPERMUTATION_COLORMAPPING;
4746 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4748 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4749 if (r_shadow_usingshadowmaprect)
4750 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4751 if (r_shadow_usingshadowmap2d)
4752 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4754 if (r_shadow_shadowmapsampler)
4755 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4756 if (r_shadow_shadowmappcf > 1)
4757 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4758 else if (r_shadow_shadowmappcf)
4759 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4761 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4762 permutation |= SHADERPERMUTATION_REFLECTION;
4763 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4764 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4765 if (rsurface.texture->reflectmasktexture)
4766 permutation |= SHADERPERMUTATION_REFLECTCUBE;
4767 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4769 // deluxemapping (light direction texture)
4770 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4771 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4773 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4774 permutation |= SHADERPERMUTATION_DIFFUSE;
4775 if (specularscale > 0)
4777 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4778 if (r_shadow_glossexact.integer)
4779 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4781 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4782 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4783 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4785 R_Mesh_ColorPointer(NULL, 0, 0);
4787 else if (r_glsl_deluxemapping.integer >= 2)
4789 // fake deluxemapping (uniform light direction in tangentspace)
4790 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4791 permutation |= SHADERPERMUTATION_DIFFUSE;
4792 if (specularscale > 0)
4794 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4795 if (r_shadow_glossexact.integer)
4796 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4798 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4799 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4800 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4802 R_Mesh_ColorPointer(NULL, 0, 0);
4804 else if (rsurface.uselightmaptexture)
4806 // ordinary lightmapping (q1bsp, q3bsp)
4807 mode = SHADERMODE_LIGHTMAP;
4808 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4809 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4810 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4812 R_Mesh_ColorPointer(NULL, 0, 0);
4816 // ordinary vertex coloring (q3bsp)
4817 mode = SHADERMODE_VERTEXCOLOR;
4818 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4819 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4821 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4822 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4824 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4825 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4826 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4830 R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4831 R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4832 R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4834 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4835 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4837 switch(vid.renderpath)
4839 case RENDERPATH_GL20:
4840 R_SetupShader_SetPermutationGLSL(mode, permutation);
4841 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4842 if (mode == SHADERMODE_LIGHTSOURCE)
4844 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4845 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4846 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4847 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);
4848 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);
4849 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);
4851 // additive passes are only darkened by fog, not tinted
4852 if (r_glsl_permutation->loc_FogColor >= 0)
4853 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4854 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4858 if (mode == SHADERMODE_FLATCOLOR)
4860 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4862 else if (mode == SHADERMODE_LIGHTDIRECTION)
4864 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]);
4865 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]);
4866 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);
4867 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);
4868 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);
4869 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]);
4870 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]);
4874 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]);
4875 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]);
4876 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);
4877 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);
4878 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);
4880 // additive passes are only darkened by fog, not tinted
4881 if (r_glsl_permutation->loc_FogColor >= 0)
4883 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4884 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4886 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4888 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);
4889 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]);
4890 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]);
4891 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4892 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4893 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4894 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4895 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4897 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4898 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4899 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4900 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]);
4901 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]);
4903 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4904 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4905 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4906 if (r_glsl_permutation->loc_Color_Pants >= 0)
4908 if (rsurface.texture->pantstexture)
4909 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4911 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4913 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4915 if (rsurface.texture->shirttexture)
4916 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4918 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4920 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]);
4921 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4922 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4923 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4924 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4925 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]);
4926 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4928 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
4929 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
4930 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
4931 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
4932 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
4933 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
4934 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
4935 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
4936 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
4937 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
4938 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
4939 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
4940 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
4941 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
4942 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4943 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
4944 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_white );
4945 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , r_texture_blanknormalmap );
4946 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
4947 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , r_texture_white );
4948 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , r_texture_white );
4949 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
4950 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
4951 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
4952 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
4953 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4955 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
4956 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
4957 if (rsurface.rtlight)
4959 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
4960 if (r_shadow_usingshadowmapcube)
4961 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4962 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
4967 case RENDERPATH_CGGL:
4969 R_SetupShader_SetPermutationCG(mode, permutation);
4970 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
4971 if (mode == SHADERMODE_LIGHTSOURCE)
4973 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4974 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4978 if (mode == SHADERMODE_LIGHTDIRECTION)
4980 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
4983 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4984 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4985 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
4986 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4987 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
4990 if (mode == SHADERMODE_LIGHTSOURCE)
4992 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4993 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4994 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
4995 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
4996 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
4998 // additive passes are only darkened by fog, not tinted
4999 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5000 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5004 if (mode == SHADERMODE_FLATCOLOR)
5006 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5008 else if (mode == SHADERMODE_LIGHTDIRECTION)
5010 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
5011 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
5012 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
5013 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
5014 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
5015 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
5016 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
5020 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
5021 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
5022 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
5023 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
5024 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
5026 // additive passes are only darkened by fog, not tinted
5027 if (r_cg_permutation->fp_FogColor)
5029 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5030 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5032 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5035 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
5036 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
5037 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
5038 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5039 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5040 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5041 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5042 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5044 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
5045 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
5046 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5047 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5048 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5049 if (r_cg_permutation->fp_Color_Pants)
5051 if (rsurface.texture->pantstexture)
5052 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5054 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5057 if (r_cg_permutation->fp_Color_Shirt)
5059 if (rsurface.texture->shirttexture)
5060 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5062 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5065 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
5066 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5067 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5068 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5069 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5070 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
5071 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5073 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5074 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5075 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5076 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5077 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5078 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5079 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5080 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5081 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5082 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5083 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5084 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5085 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5086 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5087 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
5088 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5089 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , r_texture_white );CHECKCGERROR
5090 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , r_texture_blanknormalmap );CHECKCGERROR
5091 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5092 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , r_texture_white );CHECKCGERROR
5093 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , r_texture_white );CHECKCGERROR
5094 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5095 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5096 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5097 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5098 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5100 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5101 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5102 if (rsurface.rtlight)
5104 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5105 if (r_shadow_usingshadowmapcube)
5106 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5107 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5114 case RENDERPATH_GL13:
5115 case RENDERPATH_GL11:
5120 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5122 // select a permutation of the lighting shader appropriate to this
5123 // combination of texture, entity, light source, and fogging, only use the
5124 // minimum features necessary to avoid wasting rendering time in the
5125 // fragment shader on features that are not being used
5126 unsigned int permutation = 0;
5127 unsigned int mode = 0;
5128 const float *lightcolorbase = rtlight->currentcolor;
5129 float ambientscale = rtlight->ambientscale;
5130 float diffusescale = rtlight->diffusescale;
5131 float specularscale = rtlight->specularscale;
5132 // this is the location of the light in view space
5133 vec3_t viewlightorigin;
5134 // this transforms from view space (camera) to light space (cubemap)
5135 matrix4x4_t viewtolight;
5136 matrix4x4_t lighttoview;
5137 float viewtolight16f[16];
5138 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5140 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5141 if (rtlight->currentcubemap != r_texture_whitecube)
5142 permutation |= SHADERPERMUTATION_CUBEFILTER;
5143 if (diffusescale > 0)
5144 permutation |= SHADERPERMUTATION_DIFFUSE;
5145 if (specularscale > 0)
5147 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5148 if (r_shadow_glossexact.integer)
5149 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5151 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5153 if (r_shadow_usingshadowmaprect)
5154 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5155 if (r_shadow_usingshadowmap2d)
5156 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5157 if (r_shadow_usingshadowmapcube)
5158 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5159 else if(r_shadow_shadowmapvsdct)
5160 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5162 if (r_shadow_shadowmapsampler)
5163 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5164 if (r_shadow_shadowmappcf > 1)
5165 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5166 else if (r_shadow_shadowmappcf)
5167 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5169 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5170 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5171 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5172 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5173 switch(vid.renderpath)
5175 case RENDERPATH_GL20:
5176 R_SetupShader_SetPermutationGLSL(mode, permutation);
5177 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5178 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
5179 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);
5180 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);
5181 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);
5182 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]);
5183 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]);
5184 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));
5185 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]);
5186 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5188 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5189 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5190 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5191 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5192 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
5193 if (r_shadow_usingshadowmapcube)
5194 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5195 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
5196 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5198 case RENDERPATH_CGGL:
5200 R_SetupShader_SetPermutationCG(mode, permutation);
5201 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5202 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5203 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
5204 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
5205 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
5206 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
5207 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
5208 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
5209 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
5210 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5212 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5213 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5214 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5215 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5216 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
5217 if (r_shadow_usingshadowmapcube)
5218 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5219 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5220 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5223 case RENDERPATH_GL13:
5224 case RENDERPATH_GL11:
5229 #define SKINFRAME_HASH 1024
5233 int loadsequence; // incremented each level change
5234 memexpandablearray_t array;
5235 skinframe_t *hash[SKINFRAME_HASH];
5238 r_skinframe_t r_skinframe;
5240 void R_SkinFrame_PrepareForPurge(void)
5242 r_skinframe.loadsequence++;
5243 // wrap it without hitting zero
5244 if (r_skinframe.loadsequence >= 200)
5245 r_skinframe.loadsequence = 1;
5248 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5252 // mark the skinframe as used for the purging code
5253 skinframe->loadsequence = r_skinframe.loadsequence;
5256 void R_SkinFrame_Purge(void)
5260 for (i = 0;i < SKINFRAME_HASH;i++)
5262 for (s = r_skinframe.hash[i];s;s = s->next)
5264 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5266 if (s->merged == s->base)
5268 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5269 R_PurgeTexture(s->stain );s->stain = NULL;
5270 R_PurgeTexture(s->merged);s->merged = NULL;
5271 R_PurgeTexture(s->base );s->base = NULL;
5272 R_PurgeTexture(s->pants );s->pants = NULL;
5273 R_PurgeTexture(s->shirt );s->shirt = NULL;
5274 R_PurgeTexture(s->nmap );s->nmap = NULL;
5275 R_PurgeTexture(s->gloss );s->gloss = NULL;
5276 R_PurgeTexture(s->glow );s->glow = NULL;
5277 R_PurgeTexture(s->fog );s->fog = NULL;
5278 R_PurgeTexture(s->reflect);s->reflect = NULL;
5279 s->loadsequence = 0;
5285 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5287 char basename[MAX_QPATH];
5289 Image_StripImageExtension(name, basename, sizeof(basename));
5291 if( last == NULL ) {
5293 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5294 item = r_skinframe.hash[hashindex];
5299 // linearly search through the hash bucket
5300 for( ; item ; item = item->next ) {
5301 if( !strcmp( item->basename, basename ) ) {
5308 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5312 char basename[MAX_QPATH];
5314 Image_StripImageExtension(name, basename, sizeof(basename));
5316 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5317 for (item = r_skinframe.hash[hashindex];item;item = item->next)
5318 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5322 rtexture_t *dyntexture;
5323 // check whether its a dynamic texture
5324 dyntexture = CL_GetDynTexture( basename );
5325 if (!add && !dyntexture)
5327 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5328 memset(item, 0, sizeof(*item));
5329 strlcpy(item->basename, basename, sizeof(item->basename));
5330 item->base = dyntexture; // either NULL or dyntexture handle
5331 item->textureflags = textureflags;
5332 item->comparewidth = comparewidth;
5333 item->compareheight = compareheight;
5334 item->comparecrc = comparecrc;
5335 item->next = r_skinframe.hash[hashindex];
5336 r_skinframe.hash[hashindex] = item;
5338 else if( item->base == NULL )
5340 rtexture_t *dyntexture;
5341 // check whether its a dynamic texture
5342 // 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]
5343 dyntexture = CL_GetDynTexture( basename );
5344 item->base = dyntexture; // either NULL or dyntexture handle
5347 R_SkinFrame_MarkUsed(item);
5351 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5353 unsigned long long avgcolor[5], wsum; \
5361 for(pix = 0; pix < cnt; ++pix) \
5364 for(comp = 0; comp < 3; ++comp) \
5366 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5369 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5371 for(comp = 0; comp < 3; ++comp) \
5372 avgcolor[comp] += getpixel * w; \
5375 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5376 avgcolor[4] += getpixel; \
5378 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5380 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5381 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5382 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5383 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5386 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5389 unsigned char *pixels;
5390 unsigned char *bumppixels;
5391 unsigned char *basepixels = NULL;
5392 int basepixels_width = 0;
5393 int basepixels_height = 0;
5394 skinframe_t *skinframe;
5395 rtexture_t *ddsbase = NULL;
5396 qboolean ddshasalpha = false;
5397 float ddsavgcolor[4];
5398 char basename[MAX_QPATH];
5400 if (cls.state == ca_dedicated)
5403 // return an existing skinframe if already loaded
5404 // if loading of the first image fails, don't make a new skinframe as it
5405 // would cause all future lookups of this to be missing
5406 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5407 if (skinframe && skinframe->base)
5410 Image_StripImageExtension(name, basename, sizeof(basename));
5412 // check for DDS texture file first
5413 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5415 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5416 if (basepixels == NULL)
5420 if (developer_loading.integer)
5421 Con_Printf("loading skin \"%s\"\n", name);
5423 // we've got some pixels to store, so really allocate this new texture now
5425 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5426 skinframe->stain = NULL;
5427 skinframe->merged = NULL;
5428 skinframe->base = NULL;
5429 skinframe->pants = NULL;
5430 skinframe->shirt = NULL;
5431 skinframe->nmap = NULL;
5432 skinframe->gloss = NULL;
5433 skinframe->glow = NULL;
5434 skinframe->fog = NULL;
5435 skinframe->reflect = NULL;
5436 skinframe->hasalpha = false;
5440 skinframe->base = ddsbase;
5441 skinframe->hasalpha = ddshasalpha;
5442 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5443 if (r_loadfog && skinframe->hasalpha)
5444 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5445 //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]);
5449 basepixels_width = image_width;
5450 basepixels_height = image_height;
5451 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);
5452 if (textureflags & TEXF_ALPHA)
5454 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5456 if (basepixels[j] < 255)
5458 skinframe->hasalpha = true;
5462 if (r_loadfog && skinframe->hasalpha)
5464 // has transparent pixels
5465 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5466 for (j = 0;j < image_width * image_height * 4;j += 4)
5471 pixels[j+3] = basepixels[j+3];
5473 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);
5477 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5478 //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]);
5479 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5480 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5481 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5482 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5487 if (r_loadnormalmap)
5488 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5489 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5491 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5492 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5493 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5494 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5497 // _norm is the name used by tenebrae and has been adopted as standard
5498 if (r_loadnormalmap && skinframe->nmap == NULL)
5500 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5502 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);
5506 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5508 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5509 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5510 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5512 Mem_Free(bumppixels);
5514 else if (r_shadow_bumpscale_basetexture.value > 0)
5516 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5517 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5518 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);
5521 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5522 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5525 // _luma is supported only for tenebrae compatibility
5526 // _glow is the preferred name
5527 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))))
5529 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);
5530 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5531 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5532 Mem_Free(pixels);pixels = NULL;
5535 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5537 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);
5538 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5539 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5544 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5546 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);
5547 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5548 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5553 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5555 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);
5556 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5557 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5562 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5564 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);
5565 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5566 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5572 Mem_Free(basepixels);
5577 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5578 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5581 unsigned char *temp1, *temp2;
5582 skinframe_t *skinframe;
5584 if (cls.state == ca_dedicated)
5587 // if already loaded just return it, otherwise make a new skinframe
5588 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5589 if (skinframe && skinframe->base)
5592 skinframe->stain = NULL;
5593 skinframe->merged = NULL;
5594 skinframe->base = NULL;
5595 skinframe->pants = NULL;
5596 skinframe->shirt = NULL;
5597 skinframe->nmap = NULL;
5598 skinframe->gloss = NULL;
5599 skinframe->glow = NULL;
5600 skinframe->fog = NULL;
5601 skinframe->reflect = NULL;
5602 skinframe->hasalpha = false;
5604 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5608 if (developer_loading.integer)
5609 Con_Printf("loading 32bit skin \"%s\"\n", name);
5611 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5613 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5614 temp2 = temp1 + width * height * 4;
5615 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5616 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5619 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5620 if (textureflags & TEXF_ALPHA)
5622 for (i = 3;i < width * height * 4;i += 4)
5624 if (skindata[i] < 255)
5626 skinframe->hasalpha = true;
5630 if (r_loadfog && skinframe->hasalpha)
5632 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5633 memcpy(fogpixels, skindata, width * height * 4);
5634 for (i = 0;i < width * height * 4;i += 4)
5635 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5636 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5637 Mem_Free(fogpixels);
5641 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5642 //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]);
5647 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5651 skinframe_t *skinframe;
5653 if (cls.state == ca_dedicated)
5656 // if already loaded just return it, otherwise make a new skinframe
5657 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5658 if (skinframe && skinframe->base)
5661 skinframe->stain = NULL;
5662 skinframe->merged = NULL;
5663 skinframe->base = NULL;
5664 skinframe->pants = NULL;
5665 skinframe->shirt = NULL;
5666 skinframe->nmap = NULL;
5667 skinframe->gloss = NULL;
5668 skinframe->glow = NULL;
5669 skinframe->fog = NULL;
5670 skinframe->reflect = NULL;
5671 skinframe->hasalpha = false;
5673 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5677 if (developer_loading.integer)
5678 Con_Printf("loading quake skin \"%s\"\n", name);
5680 // 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)
5681 skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5682 memcpy(skinframe->qpixels, skindata, width*height);
5683 skinframe->qwidth = width;
5684 skinframe->qheight = height;
5687 for (i = 0;i < width * height;i++)
5688 featuresmask |= palette_featureflags[skindata[i]];
5690 skinframe->hasalpha = false;
5691 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5692 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5693 skinframe->qgeneratemerged = true;
5694 skinframe->qgeneratebase = skinframe->qhascolormapping;
5695 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5697 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5698 //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]);
5703 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5707 unsigned char *skindata;
5709 if (!skinframe->qpixels)
5712 if (!skinframe->qhascolormapping)
5713 colormapped = false;
5717 if (!skinframe->qgeneratebase)
5722 if (!skinframe->qgeneratemerged)
5726 width = skinframe->qwidth;
5727 height = skinframe->qheight;
5728 skindata = skinframe->qpixels;
5730 if (skinframe->qgeneratenmap)
5732 unsigned char *temp1, *temp2;
5733 skinframe->qgeneratenmap = false;
5734 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5735 temp2 = temp1 + width * height * 4;
5736 // use either a custom palette or the quake palette
5737 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5738 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5739 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5743 if (skinframe->qgenerateglow)
5745 skinframe->qgenerateglow = false;
5746 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5751 skinframe->qgeneratebase = false;
5752 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);
5753 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5754 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5758 skinframe->qgeneratemerged = false;
5759 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5762 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5764 Mem_Free(skinframe->qpixels);
5765 skinframe->qpixels = NULL;
5769 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)
5772 skinframe_t *skinframe;
5774 if (cls.state == ca_dedicated)
5777 // if already loaded just return it, otherwise make a new skinframe
5778 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5779 if (skinframe && skinframe->base)
5782 skinframe->stain = NULL;
5783 skinframe->merged = NULL;
5784 skinframe->base = NULL;
5785 skinframe->pants = NULL;
5786 skinframe->shirt = NULL;
5787 skinframe->nmap = NULL;
5788 skinframe->gloss = NULL;
5789 skinframe->glow = NULL;
5790 skinframe->fog = NULL;
5791 skinframe->reflect = NULL;
5792 skinframe->hasalpha = false;
5794 // if no data was provided, then clearly the caller wanted to get a blank skinframe
5798 if (developer_loading.integer)
5799 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5801 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5802 if (textureflags & TEXF_ALPHA)
5804 for (i = 0;i < width * height;i++)
5806 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5808 skinframe->hasalpha = true;
5812 if (r_loadfog && skinframe->hasalpha)
5813 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5816 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5817 //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]);
5822 skinframe_t *R_SkinFrame_LoadMissing(void)
5824 skinframe_t *skinframe;
5826 if (cls.state == ca_dedicated)
5829 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5830 skinframe->stain = NULL;
5831 skinframe->merged = NULL;
5832 skinframe->base = NULL;
5833 skinframe->pants = NULL;
5834 skinframe->shirt = NULL;
5835 skinframe->nmap = NULL;
5836 skinframe->gloss = NULL;
5837 skinframe->glow = NULL;
5838 skinframe->fog = NULL;
5839 skinframe->reflect = NULL;
5840 skinframe->hasalpha = false;
5842 skinframe->avgcolor[0] = rand() / RAND_MAX;
5843 skinframe->avgcolor[1] = rand() / RAND_MAX;
5844 skinframe->avgcolor[2] = rand() / RAND_MAX;
5845 skinframe->avgcolor[3] = 1;
5850 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5851 typedef struct suffixinfo_s
5854 qboolean flipx, flipy, flipdiagonal;
5857 static suffixinfo_t suffix[3][6] =
5860 {"px", false, false, false},
5861 {"nx", false, false, false},
5862 {"py", false, false, false},
5863 {"ny", false, false, false},
5864 {"pz", false, false, false},
5865 {"nz", false, false, false}
5868 {"posx", false, false, false},
5869 {"negx", false, false, false},
5870 {"posy", false, false, false},
5871 {"negy", false, false, false},
5872 {"posz", false, false, false},
5873 {"negz", false, false, false}
5876 {"rt", true, false, true},
5877 {"lf", false, true, true},
5878 {"ft", true, true, false},
5879 {"bk", false, false, false},
5880 {"up", true, false, true},
5881 {"dn", true, false, true}
5885 static int componentorder[4] = {0, 1, 2, 3};
5887 rtexture_t *R_LoadCubemap(const char *basename)
5889 int i, j, cubemapsize;
5890 unsigned char *cubemappixels, *image_buffer;
5891 rtexture_t *cubemaptexture;
5893 // must start 0 so the first loadimagepixels has no requested width/height
5895 cubemappixels = NULL;
5896 cubemaptexture = NULL;
5897 // keep trying different suffix groups (posx, px, rt) until one loads
5898 for (j = 0;j < 3 && !cubemappixels;j++)
5900 // load the 6 images in the suffix group
5901 for (i = 0;i < 6;i++)
5903 // generate an image name based on the base and and suffix
5904 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5906 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5908 // an image loaded, make sure width and height are equal
5909 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5911 // if this is the first image to load successfully, allocate the cubemap memory
5912 if (!cubemappixels && image_width >= 1)
5914 cubemapsize = image_width;
5915 // note this clears to black, so unavailable sides are black
5916 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5918 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5920 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);
5923 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5925 Mem_Free(image_buffer);
5929 // if a cubemap loaded, upload it
5932 if (developer_loading.integer)
5933 Con_Printf("loading cubemap \"%s\"\n", basename);
5935 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5936 Mem_Free(cubemappixels);
5940 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5941 if (developer_loading.integer)
5943 Con_Printf("(tried tried images ");
5944 for (j = 0;j < 3;j++)
5945 for (i = 0;i < 6;i++)
5946 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5947 Con_Print(" and was unable to find any of them).\n");
5950 return cubemaptexture;
5953 rtexture_t *R_GetCubemap(const char *basename)
5956 for (i = 0;i < r_texture_numcubemaps;i++)
5957 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
5958 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
5959 if (i >= MAX_CUBEMAPS)
5960 return r_texture_whitecube;
5961 r_texture_numcubemaps++;
5962 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
5963 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
5964 return r_texture_cubemaps[i].texture;
5967 void R_FreeCubemaps(void)
5970 for (i = 0;i < r_texture_numcubemaps;i++)
5972 if (developer_loading.integer)
5973 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
5974 if (r_texture_cubemaps[i].texture)
5975 R_FreeTexture(r_texture_cubemaps[i].texture);
5977 r_texture_numcubemaps = 0;
5980 void R_Main_FreeViewCache(void)
5982 if (r_refdef.viewcache.entityvisible)
5983 Mem_Free(r_refdef.viewcache.entityvisible);
5984 if (r_refdef.viewcache.world_pvsbits)
5985 Mem_Free(r_refdef.viewcache.world_pvsbits);
5986 if (r_refdef.viewcache.world_leafvisible)
5987 Mem_Free(r_refdef.viewcache.world_leafvisible);
5988 if (r_refdef.viewcache.world_surfacevisible)
5989 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5990 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5993 void R_Main_ResizeViewCache(void)
5995 int numentities = r_refdef.scene.numentities;
5996 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5997 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5998 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5999 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6000 if (r_refdef.viewcache.maxentities < numentities)
6002 r_refdef.viewcache.maxentities = numentities;
6003 if (r_refdef.viewcache.entityvisible)
6004 Mem_Free(r_refdef.viewcache.entityvisible);
6005 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6007 if (r_refdef.viewcache.world_numclusters != numclusters)
6009 r_refdef.viewcache.world_numclusters = numclusters;
6010 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6011 if (r_refdef.viewcache.world_pvsbits)
6012 Mem_Free(r_refdef.viewcache.world_pvsbits);
6013 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6015 if (r_refdef.viewcache.world_numleafs != numleafs)
6017 r_refdef.viewcache.world_numleafs = numleafs;
6018 if (r_refdef.viewcache.world_leafvisible)
6019 Mem_Free(r_refdef.viewcache.world_leafvisible);
6020 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6022 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6024 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6025 if (r_refdef.viewcache.world_surfacevisible)
6026 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6027 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6031 extern rtexture_t *loadingscreentexture;
6032 void gl_main_start(void)
6034 loadingscreentexture = NULL;
6035 r_texture_blanknormalmap = NULL;
6036 r_texture_white = NULL;
6037 r_texture_grey128 = NULL;
6038 r_texture_black = NULL;
6039 r_texture_whitecube = NULL;
6040 r_texture_normalizationcube = NULL;
6041 r_texture_fogattenuation = NULL;
6042 r_texture_gammaramps = NULL;
6043 r_texture_numcubemaps = 0;
6045 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6046 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6048 switch(vid.renderpath)
6050 case RENDERPATH_GL20:
6051 case RENDERPATH_CGGL:
6052 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6053 Cvar_SetValueQuick(&gl_combine, 1);
6054 Cvar_SetValueQuick(&r_glsl, 1);
6055 r_loadnormalmap = true;
6059 case RENDERPATH_GL13:
6060 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6061 Cvar_SetValueQuick(&gl_combine, 1);
6062 Cvar_SetValueQuick(&r_glsl, 0);
6063 r_loadnormalmap = false;
6064 r_loadgloss = false;
6067 case RENDERPATH_GL11:
6068 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6069 Cvar_SetValueQuick(&gl_combine, 0);
6070 Cvar_SetValueQuick(&r_glsl, 0);
6071 r_loadnormalmap = false;
6072 r_loadgloss = false;
6078 R_FrameData_Reset();
6082 memset(r_queries, 0, sizeof(r_queries));
6084 r_qwskincache = NULL;
6085 r_qwskincache_size = 0;
6087 // set up r_skinframe loading system for textures
6088 memset(&r_skinframe, 0, sizeof(r_skinframe));
6089 r_skinframe.loadsequence = 1;
6090 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6092 r_main_texturepool = R_AllocTexturePool();
6093 R_BuildBlankTextures();
6095 if (vid.support.arb_texture_cube_map)
6098 R_BuildNormalizationCube();
6100 r_texture_fogattenuation = NULL;
6101 r_texture_gammaramps = NULL;
6102 //r_texture_fogintensity = NULL;
6103 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6104 memset(&r_waterstate, 0, sizeof(r_waterstate));
6105 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6106 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6107 glslshaderstring = NULL;
6109 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6110 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6111 cgshaderstring = NULL;
6113 memset(&r_svbsp, 0, sizeof (r_svbsp));
6115 r_refdef.fogmasktable_density = 0;
6118 void gl_main_shutdown(void)
6121 R_FrameData_Reset();
6123 R_Main_FreeViewCache();
6126 qglDeleteQueriesARB(r_maxqueries, r_queries);
6130 memset(r_queries, 0, sizeof(r_queries));
6132 r_qwskincache = NULL;
6133 r_qwskincache_size = 0;
6135 // clear out the r_skinframe state
6136 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6137 memset(&r_skinframe, 0, sizeof(r_skinframe));
6140 Mem_Free(r_svbsp.nodes);
6141 memset(&r_svbsp, 0, sizeof (r_svbsp));
6142 R_FreeTexturePool(&r_main_texturepool);
6143 loadingscreentexture = NULL;
6144 r_texture_blanknormalmap = NULL;
6145 r_texture_white = NULL;
6146 r_texture_grey128 = NULL;
6147 r_texture_black = NULL;
6148 r_texture_whitecube = NULL;
6149 r_texture_normalizationcube = NULL;
6150 r_texture_fogattenuation = NULL;
6151 r_texture_gammaramps = NULL;
6152 r_texture_numcubemaps = 0;
6153 //r_texture_fogintensity = NULL;
6154 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6155 memset(&r_waterstate, 0, sizeof(r_waterstate));
6159 extern void CL_ParseEntityLump(char *entitystring);
6160 void gl_main_newmap(void)
6162 // FIXME: move this code to client
6164 char *entities, entname[MAX_QPATH];
6166 Mem_Free(r_qwskincache);
6167 r_qwskincache = NULL;
6168 r_qwskincache_size = 0;
6171 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6172 l = (int)strlen(entname) - 4;
6173 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6175 memcpy(entname + l, ".ent", 5);
6176 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6178 CL_ParseEntityLump(entities);
6183 if (cl.worldmodel->brush.entities)
6184 CL_ParseEntityLump(cl.worldmodel->brush.entities);
6186 R_Main_FreeViewCache();
6188 R_FrameData_Reset();
6191 void GL_Main_Init(void)
6193 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6195 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6196 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6197 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6198 if (gamemode == GAME_NEHAHRA)
6200 Cvar_RegisterVariable (&gl_fogenable);
6201 Cvar_RegisterVariable (&gl_fogdensity);
6202 Cvar_RegisterVariable (&gl_fogred);
6203 Cvar_RegisterVariable (&gl_foggreen);
6204 Cvar_RegisterVariable (&gl_fogblue);
6205 Cvar_RegisterVariable (&gl_fogstart);
6206 Cvar_RegisterVariable (&gl_fogend);
6207 Cvar_RegisterVariable (&gl_skyclip);
6209 Cvar_RegisterVariable(&r_motionblur);
6210 Cvar_RegisterVariable(&r_motionblur_maxblur);
6211 Cvar_RegisterVariable(&r_motionblur_bmin);
6212 Cvar_RegisterVariable(&r_motionblur_vmin);
6213 Cvar_RegisterVariable(&r_motionblur_vmax);
6214 Cvar_RegisterVariable(&r_motionblur_vcoeff);
6215 Cvar_RegisterVariable(&r_motionblur_randomize);
6216 Cvar_RegisterVariable(&r_damageblur);
6217 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6218 Cvar_RegisterVariable(&r_equalize_entities_minambient);
6219 Cvar_RegisterVariable(&r_equalize_entities_by);
6220 Cvar_RegisterVariable(&r_equalize_entities_to);
6221 Cvar_RegisterVariable(&r_depthfirst);
6222 Cvar_RegisterVariable(&r_useinfinitefarclip);
6223 Cvar_RegisterVariable(&r_farclip_base);
6224 Cvar_RegisterVariable(&r_farclip_world);
6225 Cvar_RegisterVariable(&r_nearclip);
6226 Cvar_RegisterVariable(&r_showbboxes);
6227 Cvar_RegisterVariable(&r_showsurfaces);
6228 Cvar_RegisterVariable(&r_showtris);
6229 Cvar_RegisterVariable(&r_shownormals);
6230 Cvar_RegisterVariable(&r_showlighting);
6231 Cvar_RegisterVariable(&r_showshadowvolumes);
6232 Cvar_RegisterVariable(&r_showcollisionbrushes);
6233 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6234 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6235 Cvar_RegisterVariable(&r_showdisabledepthtest);
6236 Cvar_RegisterVariable(&r_drawportals);
6237 Cvar_RegisterVariable(&r_drawentities);
6238 Cvar_RegisterVariable(&r_cullentities_trace);
6239 Cvar_RegisterVariable(&r_cullentities_trace_samples);
6240 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6241 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6242 Cvar_RegisterVariable(&r_cullentities_trace_delay);
6243 Cvar_RegisterVariable(&r_drawviewmodel);
6244 Cvar_RegisterVariable(&r_speeds);
6245 Cvar_RegisterVariable(&r_fullbrights);
6246 Cvar_RegisterVariable(&r_wateralpha);
6247 Cvar_RegisterVariable(&r_dynamic);
6248 Cvar_RegisterVariable(&r_fullbright);
6249 Cvar_RegisterVariable(&r_shadows);
6250 Cvar_RegisterVariable(&r_shadows_darken);
6251 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6252 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6253 Cvar_RegisterVariable(&r_shadows_throwdistance);
6254 Cvar_RegisterVariable(&r_shadows_throwdirection);
6255 Cvar_RegisterVariable(&r_shadows_focus);
6256 Cvar_RegisterVariable(&r_q1bsp_skymasking);
6257 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6258 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6259 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6260 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6261 Cvar_RegisterVariable(&r_fog_exp2);
6262 Cvar_RegisterVariable(&r_drawfog);
6263 Cvar_RegisterVariable(&r_transparentdepthmasking);
6264 Cvar_RegisterVariable(&r_texture_dds_load);
6265 Cvar_RegisterVariable(&r_texture_dds_save);
6266 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6267 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6268 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6269 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6270 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6271 Cvar_RegisterVariable(&r_textureunits);
6272 Cvar_RegisterVariable(&gl_combine);
6273 Cvar_RegisterVariable(&r_glsl);
6274 Cvar_RegisterVariable(&r_glsl_deluxemapping);
6275 Cvar_RegisterVariable(&r_glsl_offsetmapping);
6276 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6277 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6278 Cvar_RegisterVariable(&r_glsl_postprocess);
6279 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6280 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6281 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6282 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6283 Cvar_RegisterVariable(&r_water);
6284 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6285 Cvar_RegisterVariable(&r_water_clippingplanebias);
6286 Cvar_RegisterVariable(&r_water_refractdistort);
6287 Cvar_RegisterVariable(&r_water_reflectdistort);
6288 Cvar_RegisterVariable(&r_lerpsprites);
6289 Cvar_RegisterVariable(&r_lerpmodels);
6290 Cvar_RegisterVariable(&r_lerplightstyles);
6291 Cvar_RegisterVariable(&r_waterscroll);
6292 Cvar_RegisterVariable(&r_bloom);
6293 Cvar_RegisterVariable(&r_bloom_colorscale);
6294 Cvar_RegisterVariable(&r_bloom_brighten);
6295 Cvar_RegisterVariable(&r_bloom_blur);
6296 Cvar_RegisterVariable(&r_bloom_resolution);
6297 Cvar_RegisterVariable(&r_bloom_colorexponent);
6298 Cvar_RegisterVariable(&r_bloom_colorsubtract);
6299 Cvar_RegisterVariable(&r_hdr);
6300 Cvar_RegisterVariable(&r_hdr_scenebrightness);
6301 Cvar_RegisterVariable(&r_hdr_glowintensity);
6302 Cvar_RegisterVariable(&r_hdr_range);
6303 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6304 Cvar_RegisterVariable(&developer_texturelogging);
6305 Cvar_RegisterVariable(&gl_lightmaps);
6306 Cvar_RegisterVariable(&r_test);
6307 Cvar_RegisterVariable(&r_batchmode);
6308 Cvar_RegisterVariable(&r_glsl_saturation);
6309 Cvar_RegisterVariable(&r_framedatasize);
6310 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6311 Cvar_SetValue("r_fullbrights", 0);
6312 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6314 Cvar_RegisterVariable(&r_track_sprites);
6315 Cvar_RegisterVariable(&r_track_sprites_flags);
6316 Cvar_RegisterVariable(&r_track_sprites_scalew);
6317 Cvar_RegisterVariable(&r_track_sprites_scaleh);
6318 Cvar_RegisterVariable(&r_overheadsprites_perspective);
6319 Cvar_RegisterVariable(&r_overheadsprites_pushback);
6322 extern void R_Textures_Init(void);
6323 extern void GL_Draw_Init(void);
6324 extern void GL_Main_Init(void);
6325 extern void R_Shadow_Init(void);
6326 extern void R_Sky_Init(void);
6327 extern void GL_Surf_Init(void);
6328 extern void R_Particles_Init(void);
6329 extern void R_Explosion_Init(void);
6330 extern void gl_backend_init(void);
6331 extern void Sbar_Init(void);
6332 extern void R_LightningBeams_Init(void);
6333 extern void Mod_RenderInit(void);
6334 extern void Font_Init(void);
6336 void Render_Init(void)
6349 R_LightningBeams_Init();
6358 extern char *ENGINE_EXTENSIONS;
6361 gl_renderer = (const char *)qglGetString(GL_RENDERER);
6362 gl_vendor = (const char *)qglGetString(GL_VENDOR);
6363 gl_version = (const char *)qglGetString(GL_VERSION);
6364 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6368 if (!gl_platformextensions)
6369 gl_platformextensions = "";
6371 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6372 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6373 Con_Printf("GL_VERSION: %s\n", gl_version);
6374 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6375 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6377 VID_CheckExtensions();
6379 // LordHavoc: report supported extensions
6380 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6382 // clear to black (loading plaque will be seen over this)
6384 qglClearColor(0,0,0,1);CHECKGLERROR
6385 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6388 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6392 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6394 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6397 p = r_refdef.view.frustum + i;
6402 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6406 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6410 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6414 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6418 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6422 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6426 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6430 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6438 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6442 for (i = 0;i < numplanes;i++)
6449 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6453 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6457 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6461 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6465 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6469 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6473 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6477 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6485 //==================================================================================
6487 // LordHavoc: this stores temporary data used within the same frame
6489 qboolean r_framedata_failed;
6490 static size_t r_framedata_size;
6491 static size_t r_framedata_current;
6492 static void *r_framedata_base;
6494 void R_FrameData_Reset(void)
6496 if (r_framedata_base)
6497 Mem_Free(r_framedata_base);
6498 r_framedata_base = NULL;
6499 r_framedata_size = 0;
6500 r_framedata_current = 0;
6501 r_framedata_failed = false;
6504 void R_FrameData_NewFrame(void)
6507 if (r_framedata_failed)
6508 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6509 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6510 wantedsize = bound(65536, wantedsize, 128*1024*1024);
6511 if (r_framedata_size != wantedsize)
6513 r_framedata_size = wantedsize;
6514 if (r_framedata_base)
6515 Mem_Free(r_framedata_base);
6516 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6518 r_framedata_current = 0;
6519 r_framedata_failed = false;
6522 void *R_FrameData_Alloc(size_t size)
6526 // align to 16 byte boundary
6527 size = (size + 15) & ~15;
6528 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6529 r_framedata_current += size;
6532 if (r_framedata_current > r_framedata_size)
6533 r_framedata_failed = true;
6535 // return NULL on everything after a failure
6536 if (r_framedata_failed)
6542 void *R_FrameData_Store(size_t size, void *data)
6544 void *d = R_FrameData_Alloc(size);
6546 memcpy(d, data, size);
6550 //==================================================================================
6552 // LordHavoc: animcache originally written by Echon, rewritten since then
6555 * Animation cache prevents re-generating mesh data for an animated model
6556 * multiple times in one frame for lighting, shadowing, reflections, etc.
6559 void R_AnimCache_Free(void)
6563 void R_AnimCache_ClearCache(void)
6566 entity_render_t *ent;
6568 for (i = 0;i < r_refdef.scene.numentities;i++)
6570 ent = r_refdef.scene.entities[i];
6571 ent->animcache_vertex3f = NULL;
6572 ent->animcache_normal3f = NULL;
6573 ent->animcache_svector3f = NULL;
6574 ent->animcache_tvector3f = NULL;
6578 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6580 dp_model_t *model = ent->model;
6582 // see if it's already cached this frame
6583 if (ent->animcache_vertex3f)
6585 // add normals/tangents if needed
6586 if (wantnormals || wanttangents)
6588 if (ent->animcache_normal3f)
6589 wantnormals = false;
6590 if (ent->animcache_svector3f)
6591 wanttangents = false;
6592 if (wantnormals || wanttangents)
6594 numvertices = model->surfmesh.num_vertices;
6596 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6599 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6600 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6602 if (!r_framedata_failed)
6603 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6609 // see if this ent is worth caching
6610 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6612 // get some memory for this entity and generate mesh data
6613 numvertices = model->surfmesh.num_vertices;
6614 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6616 ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6619 ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6620 ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6622 if (!r_framedata_failed)
6623 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6625 return !r_framedata_failed;
6628 void R_AnimCache_CacheVisibleEntities(void)
6631 qboolean wantnormals = !r_showsurfaces.integer;
6632 qboolean wanttangents = !r_showsurfaces.integer;
6634 switch(vid.renderpath)
6636 case RENDERPATH_GL20:
6637 case RENDERPATH_CGGL:
6639 case RENDERPATH_GL13:
6640 case RENDERPATH_GL11:
6641 wanttangents = false;
6645 // TODO: thread this
6646 // NOTE: R_PrepareRTLights() also caches entities
6648 for (i = 0;i < r_refdef.scene.numentities;i++)
6649 if (r_refdef.viewcache.entityvisible[i])
6650 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6653 //==================================================================================
6655 static void R_View_UpdateEntityLighting (void)
6658 entity_render_t *ent;
6659 vec3_t tempdiffusenormal, avg;
6660 vec_t f, fa, fd, fdd;
6661 qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6663 for (i = 0;i < r_refdef.scene.numentities;i++)
6665 ent = r_refdef.scene.entities[i];
6667 // skip unseen models
6668 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6672 if (ent->model && ent->model->brush.num_leafs)
6674 // TODO: use modellight for r_ambient settings on world?
6675 VectorSet(ent->modellight_ambient, 0, 0, 0);
6676 VectorSet(ent->modellight_diffuse, 0, 0, 0);
6677 VectorSet(ent->modellight_lightdir, 0, 0, 1);
6681 // fetch the lighting from the worldmodel data
6682 VectorClear(ent->modellight_ambient);
6683 VectorClear(ent->modellight_diffuse);
6684 VectorClear(tempdiffusenormal);
6685 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6688 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6689 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6690 if(ent->flags & RENDER_EQUALIZE)
6692 // first fix up ambient lighting...
6693 if(r_equalize_entities_minambient.value > 0)
6695 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6698 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6699 if(fa < r_equalize_entities_minambient.value * fd)
6702 // fa'/fd' = minambient
6703 // fa'+0.25*fd' = fa+0.25*fd
6705 // fa' = fd' * minambient
6706 // fd'*(0.25+minambient) = fa+0.25*fd
6708 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6709 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6711 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6712 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
6713 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6714 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6719 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6721 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6722 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6725 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6726 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6727 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6733 VectorSet(ent->modellight_ambient, 1, 1, 1);
6735 // move the light direction into modelspace coordinates for lighting code
6736 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6737 if(VectorLength2(ent->modellight_lightdir) == 0)
6738 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6739 VectorNormalize(ent->modellight_lightdir);
6743 #define MAX_LINEOFSIGHTTRACES 64
6745 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6748 vec3_t boxmins, boxmaxs;
6751 dp_model_t *model = r_refdef.scene.worldmodel;
6753 if (!model || !model->brush.TraceLineOfSight)
6756 // expand the box a little
6757 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6758 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6759 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6760 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6761 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6762 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6764 // return true if eye is inside enlarged box
6765 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6769 VectorCopy(eye, start);
6770 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6771 if (model->brush.TraceLineOfSight(model, start, end))
6774 // try various random positions
6775 for (i = 0;i < numsamples;i++)
6777 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6778 if (model->brush.TraceLineOfSight(model, start, end))
6786 static void R_View_UpdateEntityVisible (void)
6791 entity_render_t *ent;
6793 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6794 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6795 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
6796 : RENDER_EXTERIORMODEL;
6797 if (!r_drawviewmodel.integer)
6798 renderimask |= RENDER_VIEWMODEL;
6799 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6801 // worldmodel can check visibility
6802 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6803 for (i = 0;i < r_refdef.scene.numentities;i++)
6805 ent = r_refdef.scene.entities[i];
6806 if (!(ent->flags & renderimask))
6807 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)))
6808 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))
6809 r_refdef.viewcache.entityvisible[i] = true;
6811 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6813 for (i = 0;i < r_refdef.scene.numentities;i++)
6815 ent = r_refdef.scene.entities[i];
6816 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6818 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6820 continue; // temp entities do pvs only
6821 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6822 ent->last_trace_visibility = realtime;
6823 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6824 r_refdef.viewcache.entityvisible[i] = 0;
6831 // no worldmodel or it can't check visibility
6832 for (i = 0;i < r_refdef.scene.numentities;i++)
6834 ent = r_refdef.scene.entities[i];
6835 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));
6840 /// only used if skyrendermasked, and normally returns false
6841 int R_DrawBrushModelsSky (void)
6844 entity_render_t *ent;
6847 for (i = 0;i < r_refdef.scene.numentities;i++)
6849 if (!r_refdef.viewcache.entityvisible[i])
6851 ent = r_refdef.scene.entities[i];
6852 if (!ent->model || !ent->model->DrawSky)
6854 ent->model->DrawSky(ent);
6860 static void R_DrawNoModel(entity_render_t *ent);
6861 static void R_DrawModels(void)
6864 entity_render_t *ent;
6866 for (i = 0;i < r_refdef.scene.numentities;i++)
6868 if (!r_refdef.viewcache.entityvisible[i])
6870 ent = r_refdef.scene.entities[i];
6871 r_refdef.stats.entities++;
6872 if (ent->model && ent->model->Draw != NULL)
6873 ent->model->Draw(ent);
6879 static void R_DrawModelsDepth(void)
6882 entity_render_t *ent;
6884 for (i = 0;i < r_refdef.scene.numentities;i++)
6886 if (!r_refdef.viewcache.entityvisible[i])
6888 ent = r_refdef.scene.entities[i];
6889 if (ent->model && ent->model->DrawDepth != NULL)
6890 ent->model->DrawDepth(ent);
6894 static void R_DrawModelsDebug(void)
6897 entity_render_t *ent;
6899 for (i = 0;i < r_refdef.scene.numentities;i++)
6901 if (!r_refdef.viewcache.entityvisible[i])
6903 ent = r_refdef.scene.entities[i];
6904 if (ent->model && ent->model->DrawDebug != NULL)
6905 ent->model->DrawDebug(ent);
6909 static void R_DrawModelsAddWaterPlanes(void)
6912 entity_render_t *ent;
6914 for (i = 0;i < r_refdef.scene.numentities;i++)
6916 if (!r_refdef.viewcache.entityvisible[i])
6918 ent = r_refdef.scene.entities[i];
6919 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6920 ent->model->DrawAddWaterPlanes(ent);
6924 static void R_View_SetFrustum(void)
6927 double slopex, slopey;
6928 vec3_t forward, left, up, origin;
6930 // we can't trust r_refdef.view.forward and friends in reflected scenes
6931 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6934 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6935 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6936 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6937 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6938 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6939 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6940 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6941 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6942 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6943 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6944 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6945 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6949 zNear = r_refdef.nearclip;
6950 nudge = 1.0 - 1.0 / (1<<23);
6951 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6952 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6953 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6954 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6955 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6956 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6957 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6958 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6964 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6965 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6966 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6967 r_refdef.view.frustum[0].dist = m[15] - m[12];
6969 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6970 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6971 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6972 r_refdef.view.frustum[1].dist = m[15] + m[12];
6974 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6975 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6976 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6977 r_refdef.view.frustum[2].dist = m[15] - m[13];
6979 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6980 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6981 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6982 r_refdef.view.frustum[3].dist = m[15] + m[13];
6984 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6985 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6986 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6987 r_refdef.view.frustum[4].dist = m[15] - m[14];
6989 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6990 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6991 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6992 r_refdef.view.frustum[5].dist = m[15] + m[14];
6995 if (r_refdef.view.useperspective)
6997 slopex = 1.0 / r_refdef.view.frustum_x;
6998 slopey = 1.0 / r_refdef.view.frustum_y;
6999 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7000 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
7001 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
7002 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7003 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7005 // Leaving those out was a mistake, those were in the old code, and they
7006 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7007 // I couldn't reproduce it after adding those normalizations. --blub
7008 VectorNormalize(r_refdef.view.frustum[0].normal);
7009 VectorNormalize(r_refdef.view.frustum[1].normal);
7010 VectorNormalize(r_refdef.view.frustum[2].normal);
7011 VectorNormalize(r_refdef.view.frustum[3].normal);
7013 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7014 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]);
7015 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]);
7016 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]);
7017 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
7019 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7020 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7021 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7022 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7023 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7027 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7028 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7029 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7030 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7031 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7032 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7033 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7034 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7035 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7036 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7038 r_refdef.view.numfrustumplanes = 5;
7040 if (r_refdef.view.useclipplane)
7042 r_refdef.view.numfrustumplanes = 6;
7043 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7046 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7047 PlaneClassify(r_refdef.view.frustum + i);
7049 // LordHavoc: note to all quake engine coders, Quake had a special case
7050 // for 90 degrees which assumed a square view (wrong), so I removed it,
7051 // Quake2 has it disabled as well.
7053 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7054 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7055 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7056 //PlaneClassify(&frustum[0]);
7058 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7059 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7060 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7061 //PlaneClassify(&frustum[1]);
7063 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7064 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7065 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7066 //PlaneClassify(&frustum[2]);
7068 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7069 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7070 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7071 //PlaneClassify(&frustum[3]);
7074 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7075 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7076 //PlaneClassify(&frustum[4]);
7079 void R_View_Update(void)
7081 R_Main_ResizeViewCache();
7082 R_View_SetFrustum();
7083 R_View_WorldVisibility(r_refdef.view.useclipplane);
7084 R_View_UpdateEntityVisible();
7085 R_View_UpdateEntityLighting();
7088 void R_SetupView(qboolean allowwaterclippingplane)
7090 const float *customclipplane = NULL;
7092 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7094 // LordHavoc: couldn't figure out how to make this approach the
7095 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7096 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7097 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7098 dist = r_refdef.view.clipplane.dist;
7099 plane[0] = r_refdef.view.clipplane.normal[0];
7100 plane[1] = r_refdef.view.clipplane.normal[1];
7101 plane[2] = r_refdef.view.clipplane.normal[2];
7103 customclipplane = plane;
7106 if (!r_refdef.view.useperspective)
7107 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);
7108 else if (vid.stencil && r_useinfinitefarclip.integer)
7109 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);
7111 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);
7112 R_SetViewport(&r_refdef.view.viewport);
7115 void R_EntityMatrix(const matrix4x4_t *matrix)
7117 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7119 gl_modelmatrixchanged = false;
7120 gl_modelmatrix = *matrix;
7121 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7122 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7123 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7124 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7126 switch(vid.renderpath)
7128 case RENDERPATH_GL20:
7129 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7130 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7131 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7133 case RENDERPATH_CGGL:
7136 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7137 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7138 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7141 case RENDERPATH_GL13:
7142 case RENDERPATH_GL11:
7143 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7149 void R_ResetViewRendering2D(void)
7151 r_viewport_t viewport;
7154 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7155 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);
7156 R_SetViewport(&viewport);
7157 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7158 GL_Color(1, 1, 1, 1);
7159 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7160 GL_BlendFunc(GL_ONE, GL_ZERO);
7161 GL_AlphaTest(false);
7162 GL_ScissorTest(false);
7163 GL_DepthMask(false);
7164 GL_DepthRange(0, 1);
7165 GL_DepthTest(false);
7166 R_EntityMatrix(&identitymatrix);
7167 R_Mesh_ResetTextureState();
7168 GL_PolygonOffset(0, 0);
7169 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7170 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7171 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7172 qglStencilMask(~0);CHECKGLERROR
7173 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7174 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7175 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7178 void R_ResetViewRendering3D(void)
7183 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7184 GL_Color(1, 1, 1, 1);
7185 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7186 GL_BlendFunc(GL_ONE, GL_ZERO);
7187 GL_AlphaTest(false);
7188 GL_ScissorTest(true);
7190 GL_DepthRange(0, 1);
7192 R_EntityMatrix(&identitymatrix);
7193 R_Mesh_ResetTextureState();
7194 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7195 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7196 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7197 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7198 qglStencilMask(~0);CHECKGLERROR
7199 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7200 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7201 GL_CullFace(r_refdef.view.cullface_back);
7204 void R_RenderScene(void);
7205 void R_RenderWaterPlanes(void);
7207 static void R_Water_StartFrame(void)
7210 int waterwidth, waterheight, texturewidth, textureheight;
7211 r_waterstate_waterplane_t *p;
7213 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7216 switch(vid.renderpath)
7218 case RENDERPATH_GL20:
7219 case RENDERPATH_CGGL:
7221 case RENDERPATH_GL13:
7222 case RENDERPATH_GL11:
7226 // set waterwidth and waterheight to the water resolution that will be
7227 // used (often less than the screen resolution for faster rendering)
7228 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7229 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7231 // calculate desired texture sizes
7232 // can't use water if the card does not support the texture size
7233 if (!r_water.integer || r_showsurfaces.integer)
7234 texturewidth = textureheight = waterwidth = waterheight = 0;
7235 else if (vid.support.arb_texture_non_power_of_two)
7237 texturewidth = waterwidth;
7238 textureheight = waterheight;
7242 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7243 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7246 // allocate textures as needed
7247 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7249 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7250 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7252 if (p->texture_refraction)
7253 R_FreeTexture(p->texture_refraction);
7254 p->texture_refraction = NULL;
7255 if (p->texture_reflection)
7256 R_FreeTexture(p->texture_reflection);
7257 p->texture_reflection = NULL;
7259 memset(&r_waterstate, 0, sizeof(r_waterstate));
7260 r_waterstate.texturewidth = texturewidth;
7261 r_waterstate.textureheight = textureheight;
7264 if (r_waterstate.texturewidth)
7266 r_waterstate.enabled = true;
7268 // when doing a reduced render (HDR) we want to use a smaller area
7269 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7270 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7272 // set up variables that will be used in shader setup
7273 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7274 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7275 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7276 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7279 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7280 r_waterstate.numwaterplanes = 0;
7283 void R_Water_AddWaterPlane(msurface_t *surface)
7285 int triangleindex, planeindex;
7291 r_waterstate_waterplane_t *p;
7292 texture_t *t = R_GetCurrentTexture(surface->texture);
7293 // just use the first triangle with a valid normal for any decisions
7294 VectorClear(normal);
7295 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7297 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7298 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7299 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7300 TriangleNormal(vert[0], vert[1], vert[2], normal);
7301 if (VectorLength2(normal) >= 0.001)
7305 VectorCopy(normal, plane.normal);
7306 VectorNormalize(plane.normal);
7307 plane.dist = DotProduct(vert[0], plane.normal);
7308 PlaneClassify(&plane);
7309 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7311 // skip backfaces (except if nocullface is set)
7312 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7314 VectorNegate(plane.normal, plane.normal);
7316 PlaneClassify(&plane);
7320 // find a matching plane if there is one
7321 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7322 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7324 if (planeindex >= r_waterstate.maxwaterplanes)
7325 return; // nothing we can do, out of planes
7327 // if this triangle does not fit any known plane rendered this frame, add one
7328 if (planeindex >= r_waterstate.numwaterplanes)
7330 // store the new plane
7331 r_waterstate.numwaterplanes++;
7333 // clear materialflags and pvs
7334 p->materialflags = 0;
7335 p->pvsvalid = false;
7337 // merge this surface's materialflags into the waterplane
7338 p->materialflags |= t->currentmaterialflags;
7339 // merge this surface's PVS into the waterplane
7340 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7341 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7342 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7344 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7349 static void R_Water_ProcessPlanes(void)
7351 r_refdef_view_t originalview;
7352 r_refdef_view_t myview;
7354 r_waterstate_waterplane_t *p;
7356 originalview = r_refdef.view;
7358 // make sure enough textures are allocated
7359 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7361 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7363 if (!p->texture_refraction)
7364 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);
7365 if (!p->texture_refraction)
7369 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7371 if (!p->texture_reflection)
7372 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);
7373 if (!p->texture_reflection)
7379 r_refdef.view = originalview;
7380 r_refdef.view.showdebug = false;
7381 r_refdef.view.width = r_waterstate.waterwidth;
7382 r_refdef.view.height = r_waterstate.waterheight;
7383 r_refdef.view.useclipplane = true;
7384 myview = r_refdef.view;
7385 r_waterstate.renderingscene = true;
7386 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7388 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7390 r_refdef.view = myview;
7391 // render reflected scene and copy into texture
7392 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7393 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7394 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7395 r_refdef.view.clipplane = p->plane;
7396 // reverse the cullface settings for this render
7397 r_refdef.view.cullface_front = GL_FRONT;
7398 r_refdef.view.cullface_back = GL_BACK;
7399 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7401 r_refdef.view.usecustompvs = true;
7403 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7405 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7408 R_ResetViewRendering3D();
7409 R_ClearScreen(r_refdef.fogenabled);
7413 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);
7416 // render the normal view scene and copy into texture
7417 // (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)
7418 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7420 r_waterstate.renderingrefraction = true;
7421 r_refdef.view = myview;
7422 r_refdef.view.clipplane = p->plane;
7423 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7424 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7425 PlaneClassify(&r_refdef.view.clipplane);
7427 R_ResetViewRendering3D();
7428 R_ClearScreen(r_refdef.fogenabled);
7432 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);
7433 r_waterstate.renderingrefraction = false;
7437 r_waterstate.renderingscene = false;
7438 r_refdef.view = originalview;
7439 R_ResetViewRendering3D();
7440 R_ClearScreen(r_refdef.fogenabled);
7444 r_refdef.view = originalview;
7445 r_waterstate.renderingscene = false;
7446 Cvar_SetValueQuick(&r_water, 0);
7447 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7451 void R_Bloom_StartFrame(void)
7453 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7455 switch(vid.renderpath)
7457 case RENDERPATH_GL20:
7458 case RENDERPATH_CGGL:
7460 case RENDERPATH_GL13:
7461 case RENDERPATH_GL11:
7465 // set bloomwidth and bloomheight to the bloom resolution that will be
7466 // used (often less than the screen resolution for faster rendering)
7467 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7468 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7469 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7470 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7471 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7473 // calculate desired texture sizes
7474 if (vid.support.arb_texture_non_power_of_two)
7476 screentexturewidth = r_refdef.view.width;
7477 screentextureheight = r_refdef.view.height;
7478 bloomtexturewidth = r_bloomstate.bloomwidth;
7479 bloomtextureheight = r_bloomstate.bloomheight;
7483 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7484 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7485 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7486 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7489 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))
7491 Cvar_SetValueQuick(&r_hdr, 0);
7492 Cvar_SetValueQuick(&r_bloom, 0);
7493 Cvar_SetValueQuick(&r_motionblur, 0);
7494 Cvar_SetValueQuick(&r_damageblur, 0);
7497 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)))
7498 screentexturewidth = screentextureheight = 0;
7499 if (!r_hdr.integer && !r_bloom.integer)
7500 bloomtexturewidth = bloomtextureheight = 0;
7502 // allocate textures as needed
7503 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7505 if (r_bloomstate.texture_screen)
7506 R_FreeTexture(r_bloomstate.texture_screen);
7507 r_bloomstate.texture_screen = NULL;
7508 r_bloomstate.screentexturewidth = screentexturewidth;
7509 r_bloomstate.screentextureheight = screentextureheight;
7510 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7511 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7513 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7515 if (r_bloomstate.texture_bloom)
7516 R_FreeTexture(r_bloomstate.texture_bloom);
7517 r_bloomstate.texture_bloom = NULL;
7518 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7519 r_bloomstate.bloomtextureheight = bloomtextureheight;
7520 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7521 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7524 // when doing a reduced render (HDR) we want to use a smaller area
7525 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7526 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7527 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7528 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7529 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7531 // set up a texcoord array for the full resolution screen image
7532 // (we have to keep this around to copy back during final render)
7533 r_bloomstate.screentexcoord2f[0] = 0;
7534 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7535 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7536 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7537 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7538 r_bloomstate.screentexcoord2f[5] = 0;
7539 r_bloomstate.screentexcoord2f[6] = 0;
7540 r_bloomstate.screentexcoord2f[7] = 0;
7542 // set up a texcoord array for the reduced resolution bloom image
7543 // (which will be additive blended over the screen image)
7544 r_bloomstate.bloomtexcoord2f[0] = 0;
7545 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7546 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7547 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7548 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7549 r_bloomstate.bloomtexcoord2f[5] = 0;
7550 r_bloomstate.bloomtexcoord2f[6] = 0;
7551 r_bloomstate.bloomtexcoord2f[7] = 0;
7553 if (r_hdr.integer || r_bloom.integer)
7555 r_bloomstate.enabled = true;
7556 r_bloomstate.hdr = r_hdr.integer != 0;
7559 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);
7562 void R_Bloom_CopyBloomTexture(float colorscale)
7564 r_refdef.stats.bloom++;
7566 // scale down screen texture to the bloom texture size
7568 R_SetViewport(&r_bloomstate.viewport);
7569 GL_BlendFunc(GL_ONE, GL_ZERO);
7570 GL_Color(colorscale, colorscale, colorscale, 1);
7571 // TODO: optimize with multitexture or GLSL
7572 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7573 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7574 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7575 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7577 // we now have a bloom image in the framebuffer
7578 // copy it into the bloom image texture for later processing
7579 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);
7580 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7583 void R_Bloom_CopyHDRTexture(void)
7585 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);
7586 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7589 void R_Bloom_MakeTexture(void)
7592 float xoffset, yoffset, r, brighten;
7594 r_refdef.stats.bloom++;
7596 R_ResetViewRendering2D();
7597 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7598 R_Mesh_ColorPointer(NULL, 0, 0);
7600 // we have a bloom image in the framebuffer
7602 R_SetViewport(&r_bloomstate.viewport);
7604 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7607 r = bound(0, r_bloom_colorexponent.value / x, 1);
7608 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7609 GL_Color(r, r, r, 1);
7610 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7611 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7612 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7613 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7615 // copy the vertically blurred bloom view to a texture
7616 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);
7617 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7620 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7621 brighten = r_bloom_brighten.value;
7623 brighten *= r_hdr_range.value;
7624 brighten = sqrt(brighten);
7626 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7627 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7628 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7630 for (dir = 0;dir < 2;dir++)
7632 // blend on at multiple vertical offsets to achieve a vertical blur
7633 // TODO: do offset blends using GLSL
7634 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7635 GL_BlendFunc(GL_ONE, GL_ZERO);
7636 for (x = -range;x <= range;x++)
7638 if (!dir){xoffset = 0;yoffset = x;}
7639 else {xoffset = x;yoffset = 0;}
7640 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7641 yoffset /= (float)r_bloomstate.bloomtextureheight;
7642 // compute a texcoord array with the specified x and y offset
7643 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7644 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7645 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7646 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7647 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7648 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7649 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7650 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7651 // this r value looks like a 'dot' particle, fading sharply to
7652 // black at the edges
7653 // (probably not realistic but looks good enough)
7654 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7655 //r = brighten/(range*2+1);
7656 r = brighten / (range * 2 + 1);
7658 r *= (1 - x*x/(float)(range*range));
7659 GL_Color(r, r, r, 1);
7660 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7661 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7662 GL_BlendFunc(GL_ONE, GL_ONE);
7665 // copy the vertically blurred bloom view to a texture
7666 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);
7667 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7670 // apply subtract last
7671 // (just like it would be in a GLSL shader)
7672 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7674 GL_BlendFunc(GL_ONE, GL_ZERO);
7675 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7676 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7677 GL_Color(1, 1, 1, 1);
7678 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7679 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7681 GL_BlendFunc(GL_ONE, GL_ONE);
7682 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7683 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7684 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7685 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7686 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7687 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7688 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7690 // copy the darkened bloom view to a texture
7691 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);
7692 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7696 void R_HDR_RenderBloomTexture(void)
7698 int oldwidth, oldheight;
7699 float oldcolorscale;
7701 oldcolorscale = r_refdef.view.colorscale;
7702 oldwidth = r_refdef.view.width;
7703 oldheight = r_refdef.view.height;
7704 r_refdef.view.width = r_bloomstate.bloomwidth;
7705 r_refdef.view.height = r_bloomstate.bloomheight;
7707 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7708 // TODO: add exposure compensation features
7709 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7711 r_refdef.view.showdebug = false;
7712 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7714 R_ResetViewRendering3D();
7716 R_ClearScreen(r_refdef.fogenabled);
7717 if (r_timereport_active)
7718 R_TimeReport("HDRclear");
7721 if (r_timereport_active)
7722 R_TimeReport("visibility");
7724 // only do secondary renders with HDR if r_hdr is 2 or higher
7725 r_waterstate.numwaterplanes = 0;
7726 if (r_waterstate.enabled && r_hdr.integer >= 2)
7727 R_RenderWaterPlanes();
7729 r_refdef.view.showdebug = true;
7731 r_waterstate.numwaterplanes = 0;
7733 R_ResetViewRendering2D();
7735 R_Bloom_CopyHDRTexture();
7736 R_Bloom_MakeTexture();
7738 // restore the view settings
7739 r_refdef.view.width = oldwidth;
7740 r_refdef.view.height = oldheight;
7741 r_refdef.view.colorscale = oldcolorscale;
7743 R_ResetViewRendering3D();
7745 R_ClearScreen(r_refdef.fogenabled);
7746 if (r_timereport_active)
7747 R_TimeReport("viewclear");
7750 static void R_BlendView(void)
7752 unsigned int permutation;
7753 float uservecs[4][4];
7755 switch (vid.renderpath)
7757 case RENDERPATH_GL20:
7758 case RENDERPATH_CGGL:
7760 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7761 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7762 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7763 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7764 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7766 if (r_bloomstate.texture_screen)
7768 // make sure the buffer is available
7769 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7771 R_ResetViewRendering2D();
7772 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7773 R_Mesh_ColorPointer(NULL, 0, 0);
7775 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7777 // declare variables
7779 static float avgspeed;
7781 speed = VectorLength(cl.movement_velocity);
7783 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7784 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7786 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7787 speed = bound(0, speed, 1);
7788 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7790 // calculate values into a standard alpha
7791 cl.motionbluralpha = 1 - exp(-
7793 (r_motionblur.value * speed / 80)
7795 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7798 max(0.0001, cl.time - cl.oldtime) // fps independent
7801 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7802 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7804 if (cl.motionbluralpha > 0)
7806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7807 GL_Color(1, 1, 1, cl.motionbluralpha);
7808 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7809 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7810 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7811 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7815 // copy view into the screen texture
7816 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);
7817 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7819 else if (!r_bloomstate.texture_bloom)
7821 // we may still have to do view tint...
7822 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7824 // apply a color tint to the whole view
7825 R_ResetViewRendering2D();
7826 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7827 R_Mesh_ColorPointer(NULL, 0, 0);
7828 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7829 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7830 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7831 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7833 break; // no screen processing, no bloom, skip it
7836 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7838 // render simple bloom effect
7839 // copy the screen and shrink it and darken it for the bloom process
7840 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7841 // make the bloom texture
7842 R_Bloom_MakeTexture();
7845 #if _MSC_VER >= 1400
7846 #define sscanf sscanf_s
7848 memset(uservecs, 0, sizeof(uservecs));
7849 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7850 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7851 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7852 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7854 R_ResetViewRendering2D();
7855 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7856 R_Mesh_ColorPointer(NULL, 0, 0);
7857 GL_Color(1, 1, 1, 1);
7858 GL_BlendFunc(GL_ONE, GL_ZERO);
7859 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7860 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7862 switch(vid.renderpath)
7864 case RENDERPATH_GL20:
7865 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7866 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7867 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7868 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7869 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]);
7870 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7871 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]);
7872 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]);
7873 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]);
7874 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]);
7875 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7876 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7878 case RENDERPATH_CGGL:
7880 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7881 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7882 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7883 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7884 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
7885 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7886 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
7887 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
7888 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
7889 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
7890 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7891 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7897 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7898 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7900 case RENDERPATH_GL13:
7901 case RENDERPATH_GL11:
7902 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7904 // apply a color tint to the whole view
7905 R_ResetViewRendering2D();
7906 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7907 R_Mesh_ColorPointer(NULL, 0, 0);
7908 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7909 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7910 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7911 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7917 matrix4x4_t r_waterscrollmatrix;
7919 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7921 if (r_refdef.fog_density)
7923 r_refdef.fogcolor[0] = r_refdef.fog_red;
7924 r_refdef.fogcolor[1] = r_refdef.fog_green;
7925 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7927 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7928 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7929 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7930 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7934 VectorCopy(r_refdef.fogcolor, fogvec);
7935 // color.rgb *= ContrastBoost * SceneBrightness;
7936 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7937 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7938 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7939 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7944 void R_UpdateVariables(void)
7948 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7950 r_refdef.farclip = r_farclip_base.value;
7951 if (r_refdef.scene.worldmodel)
7952 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7953 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7955 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7956 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7957 r_refdef.polygonfactor = 0;
7958 r_refdef.polygonoffset = 0;
7959 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7960 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7962 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7963 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7964 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7965 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7966 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7967 if (r_showsurfaces.integer)
7969 r_refdef.scene.rtworld = false;
7970 r_refdef.scene.rtworldshadows = false;
7971 r_refdef.scene.rtdlight = false;
7972 r_refdef.scene.rtdlightshadows = false;
7973 r_refdef.lightmapintensity = 0;
7976 if (gamemode == GAME_NEHAHRA)
7978 if (gl_fogenable.integer)
7980 r_refdef.oldgl_fogenable = true;
7981 r_refdef.fog_density = gl_fogdensity.value;
7982 r_refdef.fog_red = gl_fogred.value;
7983 r_refdef.fog_green = gl_foggreen.value;
7984 r_refdef.fog_blue = gl_fogblue.value;
7985 r_refdef.fog_alpha = 1;
7986 r_refdef.fog_start = 0;
7987 r_refdef.fog_end = gl_skyclip.value;
7988 r_refdef.fog_height = 1<<30;
7989 r_refdef.fog_fadedepth = 128;
7991 else if (r_refdef.oldgl_fogenable)
7993 r_refdef.oldgl_fogenable = false;
7994 r_refdef.fog_density = 0;
7995 r_refdef.fog_red = 0;
7996 r_refdef.fog_green = 0;
7997 r_refdef.fog_blue = 0;
7998 r_refdef.fog_alpha = 0;
7999 r_refdef.fog_start = 0;
8000 r_refdef.fog_end = 0;
8001 r_refdef.fog_height = 1<<30;
8002 r_refdef.fog_fadedepth = 128;
8006 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8007 r_refdef.fog_start = max(0, r_refdef.fog_start);
8008 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8010 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8012 if (r_refdef.fog_density && r_drawfog.integer)
8014 r_refdef.fogenabled = true;
8015 // this is the point where the fog reaches 0.9986 alpha, which we
8016 // consider a good enough cutoff point for the texture
8017 // (0.9986 * 256 == 255.6)
8018 if (r_fog_exp2.integer)
8019 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8021 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8022 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8023 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8024 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8025 // fog color was already set
8026 // update the fog texture
8027 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)
8028 R_BuildFogTexture();
8031 r_refdef.fogenabled = false;
8033 switch(vid.renderpath)
8035 case RENDERPATH_GL20:
8036 case RENDERPATH_CGGL:
8037 if(v_glslgamma.integer && !vid_gammatables_trivial)
8039 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8041 // build GLSL gamma texture
8042 #define RAMPWIDTH 256
8043 unsigned short ramp[RAMPWIDTH * 3];
8044 unsigned char rampbgr[RAMPWIDTH][4];
8047 r_texture_gammaramps_serial = vid_gammatables_serial;
8049 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8050 for(i = 0; i < RAMPWIDTH; ++i)
8052 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8053 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8054 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8057 if (r_texture_gammaramps)
8059 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8063 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);
8069 // remove GLSL gamma texture
8072 case RENDERPATH_GL13:
8073 case RENDERPATH_GL11:
8078 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8079 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8085 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8086 if( scenetype != r_currentscenetype ) {
8087 // store the old scenetype
8088 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8089 r_currentscenetype = scenetype;
8090 // move in the new scene
8091 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8100 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8102 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8103 if( scenetype == r_currentscenetype ) {
8104 return &r_refdef.scene;
8106 return &r_scenes_store[ scenetype ];
8115 void R_RenderView(void)
8117 if (r_timereport_active)
8118 R_TimeReport("start");
8119 r_textureframe++; // used only by R_GetCurrentTexture
8120 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8122 if (!r_drawentities.integer)
8123 r_refdef.scene.numentities = 0;
8125 R_AnimCache_ClearCache();
8126 R_FrameData_NewFrame();
8128 if (r_refdef.view.isoverlay)
8130 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8131 GL_Clear( GL_DEPTH_BUFFER_BIT );
8132 R_TimeReport("depthclear");
8134 r_refdef.view.showdebug = false;
8136 r_waterstate.enabled = false;
8137 r_waterstate.numwaterplanes = 0;
8145 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8146 return; //Host_Error ("R_RenderView: NULL worldmodel");
8148 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8150 // break apart the view matrix into vectors for various purposes
8151 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8152 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8153 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8154 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8155 // make an inverted copy of the view matrix for tracking sprites
8156 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8158 R_Shadow_UpdateWorldLightSelection();
8160 R_Bloom_StartFrame();
8161 R_Water_StartFrame();
8164 if (r_timereport_active)
8165 R_TimeReport("viewsetup");
8167 R_ResetViewRendering3D();
8169 if (r_refdef.view.clear || r_refdef.fogenabled)
8171 R_ClearScreen(r_refdef.fogenabled);
8172 if (r_timereport_active)
8173 R_TimeReport("viewclear");
8175 r_refdef.view.clear = true;
8177 // this produces a bloom texture to be used in R_BlendView() later
8178 if (r_hdr.integer && r_bloomstate.bloomwidth)
8180 R_HDR_RenderBloomTexture();
8181 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8182 r_textureframe++; // used only by R_GetCurrentTexture
8185 r_refdef.view.showdebug = true;
8188 if (r_timereport_active)
8189 R_TimeReport("visibility");
8191 r_waterstate.numwaterplanes = 0;
8192 if (r_waterstate.enabled)
8193 R_RenderWaterPlanes();
8196 r_waterstate.numwaterplanes = 0;
8199 if (r_timereport_active)
8200 R_TimeReport("blendview");
8202 GL_Scissor(0, 0, vid.width, vid.height);
8203 GL_ScissorTest(false);
8207 void R_RenderWaterPlanes(void)
8209 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8211 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8212 if (r_timereport_active)
8213 R_TimeReport("waterworld");
8216 // don't let sound skip if going slow
8217 if (r_refdef.scene.extraupdate)
8220 R_DrawModelsAddWaterPlanes();
8221 if (r_timereport_active)
8222 R_TimeReport("watermodels");
8224 if (r_waterstate.numwaterplanes)
8226 R_Water_ProcessPlanes();
8227 if (r_timereport_active)
8228 R_TimeReport("waterscenes");
8232 extern void R_DrawLightningBeams (void);
8233 extern void VM_CL_AddPolygonsToMeshQueue (void);
8234 extern void R_DrawPortals (void);
8235 extern cvar_t cl_locs_show;
8236 static void R_DrawLocs(void);
8237 static void R_DrawEntityBBoxes(void);
8238 static void R_DrawModelDecals(void);
8239 extern void R_DrawModelShadows(void);
8240 extern void R_DrawModelShadowMaps(void);
8241 extern cvar_t cl_decals_newsystem;
8242 extern qboolean r_shadow_usingdeferredprepass;
8243 void R_RenderScene(void)
8245 qboolean shadowmapping = false;
8247 r_refdef.stats.renders++;
8251 // don't let sound skip if going slow
8252 if (r_refdef.scene.extraupdate)
8255 R_MeshQueue_BeginScene();
8259 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);
8261 if (cl.csqc_vidvars.drawworld)
8263 // don't let sound skip if going slow
8264 if (r_refdef.scene.extraupdate)
8267 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8269 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8270 if (r_timereport_active)
8271 R_TimeReport("worldsky");
8274 if (R_DrawBrushModelsSky() && r_timereport_active)
8275 R_TimeReport("bmodelsky");
8277 if (skyrendermasked && skyrenderlater)
8279 // we have to force off the water clipping plane while rendering sky
8283 if (r_timereport_active)
8284 R_TimeReport("sky");
8288 R_AnimCache_CacheVisibleEntities();
8289 if (r_timereport_active)
8290 R_TimeReport("animation");
8292 R_Shadow_PrepareLights();
8293 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8294 R_Shadow_PrepareModelShadows();
8295 if (r_timereport_active)
8296 R_TimeReport("preparelights");
8298 if (R_Shadow_ShadowMappingEnabled())
8299 shadowmapping = true;
8301 if (r_shadow_usingdeferredprepass)
8302 R_Shadow_DrawPrepass();
8304 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8306 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8307 if (r_timereport_active)
8308 R_TimeReport("worlddepth");
8310 if (r_depthfirst.integer >= 2)
8312 R_DrawModelsDepth();
8313 if (r_timereport_active)
8314 R_TimeReport("modeldepth");
8317 if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8319 R_DrawModelShadowMaps();
8320 R_ResetViewRendering3D();
8321 // don't let sound skip if going slow
8322 if (r_refdef.scene.extraupdate)
8326 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8328 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8329 if (r_timereport_active)
8330 R_TimeReport("world");
8333 // don't let sound skip if going slow
8334 if (r_refdef.scene.extraupdate)
8338 if (r_timereport_active)
8339 R_TimeReport("models");
8341 // don't let sound skip if going slow
8342 if (r_refdef.scene.extraupdate)
8345 if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8347 R_DrawModelShadows();
8348 R_ResetViewRendering3D();
8349 // don't let sound skip if going slow
8350 if (r_refdef.scene.extraupdate)
8354 if (!r_shadow_usingdeferredprepass)
8356 R_Shadow_DrawLights();
8357 if (r_timereport_active)
8358 R_TimeReport("rtlights");
8361 // don't let sound skip if going slow
8362 if (r_refdef.scene.extraupdate)
8365 if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8367 R_DrawModelShadows();
8368 R_ResetViewRendering3D();
8369 // don't let sound skip if going slow
8370 if (r_refdef.scene.extraupdate)
8374 if (cl.csqc_vidvars.drawworld)
8376 if (cl_decals_newsystem.integer)
8378 R_DrawModelDecals();
8379 if (r_timereport_active)
8380 R_TimeReport("modeldecals");
8385 if (r_timereport_active)
8386 R_TimeReport("decals");
8390 if (r_timereport_active)
8391 R_TimeReport("particles");
8394 if (r_timereport_active)
8395 R_TimeReport("explosions");
8397 R_DrawLightningBeams();
8398 if (r_timereport_active)
8399 R_TimeReport("lightning");
8402 VM_CL_AddPolygonsToMeshQueue();
8404 if (r_refdef.view.showdebug)
8406 if (cl_locs_show.integer)
8409 if (r_timereport_active)
8410 R_TimeReport("showlocs");
8413 if (r_drawportals.integer)
8416 if (r_timereport_active)
8417 R_TimeReport("portals");
8420 if (r_showbboxes.value > 0)
8422 R_DrawEntityBBoxes();
8423 if (r_timereport_active)
8424 R_TimeReport("bboxes");
8428 R_MeshQueue_RenderTransparent();
8429 if (r_timereport_active)
8430 R_TimeReport("drawtrans");
8432 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))
8434 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8435 if (r_timereport_active)
8436 R_TimeReport("worlddebug");
8437 R_DrawModelsDebug();
8438 if (r_timereport_active)
8439 R_TimeReport("modeldebug");
8442 if (cl.csqc_vidvars.drawworld)
8444 R_Shadow_DrawCoronas();
8445 if (r_timereport_active)
8446 R_TimeReport("coronas");
8449 // don't let sound skip if going slow
8450 if (r_refdef.scene.extraupdate)
8453 R_ResetViewRendering2D();
8456 static const unsigned short bboxelements[36] =
8466 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8469 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8471 RSurf_ActiveWorldEntity();
8473 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8474 GL_DepthMask(false);
8475 GL_DepthRange(0, 1);
8476 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8477 R_Mesh_ResetTextureState();
8479 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8480 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8481 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8482 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8483 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8484 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8485 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8486 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8487 R_FillColors(color4f, 8, cr, cg, cb, ca);
8488 if (r_refdef.fogenabled)
8490 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8492 f1 = RSurf_FogVertex(v);
8494 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8495 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8496 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8499 R_Mesh_VertexPointer(vertex3f, 0, 0);
8500 R_Mesh_ColorPointer(color4f, 0, 0);
8501 R_Mesh_ResetTextureState();
8502 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8503 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8506 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8510 prvm_edict_t *edict;
8511 prvm_prog_t *prog_save = prog;
8513 // this function draws bounding boxes of server entities
8517 GL_CullFace(GL_NONE);
8518 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8522 for (i = 0;i < numsurfaces;i++)
8524 edict = PRVM_EDICT_NUM(surfacelist[i]);
8525 switch ((int)edict->fields.server->solid)
8527 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8528 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8529 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8530 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8531 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8532 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8534 color[3] *= r_showbboxes.value;
8535 color[3] = bound(0, color[3], 1);
8536 GL_DepthTest(!r_showdisabledepthtest.integer);
8537 GL_CullFace(r_refdef.view.cullface_front);
8538 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8544 static void R_DrawEntityBBoxes(void)
8547 prvm_edict_t *edict;
8549 prvm_prog_t *prog_save = prog;
8551 // this function draws bounding boxes of server entities
8557 for (i = 0;i < prog->num_edicts;i++)
8559 edict = PRVM_EDICT_NUM(i);
8560 if (edict->priv.server->free)
8562 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8563 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8565 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8567 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8568 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8574 static const int nomodelelement3i[24] =
8586 static const unsigned short nomodelelement3s[24] =
8598 static const float nomodelvertex3f[6*3] =
8608 static const float nomodelcolor4f[6*4] =
8610 0.0f, 0.0f, 0.5f, 1.0f,
8611 0.0f, 0.0f, 0.5f, 1.0f,
8612 0.0f, 0.5f, 0.0f, 1.0f,
8613 0.0f, 0.5f, 0.0f, 1.0f,
8614 0.5f, 0.0f, 0.0f, 1.0f,
8615 0.5f, 0.0f, 0.0f, 1.0f
8618 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8624 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);
8626 // this is only called once per entity so numsurfaces is always 1, and
8627 // surfacelist is always {0}, so this code does not handle batches
8629 if (rsurface.ent_flags & RENDER_ADDITIVE)
8631 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8632 GL_DepthMask(false);
8634 else if (rsurface.colormod[3] < 1)
8636 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8637 GL_DepthMask(false);
8641 GL_BlendFunc(GL_ONE, GL_ZERO);
8644 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8645 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8646 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8647 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8648 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8649 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8650 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8651 R_Mesh_ColorPointer(color4f, 0, 0);
8652 for (i = 0, c = color4f;i < 6;i++, c += 4)
8654 c[0] *= rsurface.colormod[0];
8655 c[1] *= rsurface.colormod[1];
8656 c[2] *= rsurface.colormod[2];
8657 c[3] *= rsurface.colormod[3];
8659 if (r_refdef.fogenabled)
8661 for (i = 0, c = color4f;i < 6;i++, c += 4)
8663 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8665 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8666 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8667 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8670 R_Mesh_ResetTextureState();
8671 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8674 void R_DrawNoModel(entity_render_t *ent)
8677 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8678 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8679 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8681 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8684 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8686 vec3_t right1, right2, diff, normal;
8688 VectorSubtract (org2, org1, normal);
8690 // calculate 'right' vector for start
8691 VectorSubtract (r_refdef.view.origin, org1, diff);
8692 CrossProduct (normal, diff, right1);
8693 VectorNormalize (right1);
8695 // calculate 'right' vector for end
8696 VectorSubtract (r_refdef.view.origin, org2, diff);
8697 CrossProduct (normal, diff, right2);
8698 VectorNormalize (right2);
8700 vert[ 0] = org1[0] + width * right1[0];
8701 vert[ 1] = org1[1] + width * right1[1];
8702 vert[ 2] = org1[2] + width * right1[2];
8703 vert[ 3] = org1[0] - width * right1[0];
8704 vert[ 4] = org1[1] - width * right1[1];
8705 vert[ 5] = org1[2] - width * right1[2];
8706 vert[ 6] = org2[0] - width * right2[0];
8707 vert[ 7] = org2[1] - width * right2[1];
8708 vert[ 8] = org2[2] - width * right2[2];
8709 vert[ 9] = org2[0] + width * right2[0];
8710 vert[10] = org2[1] + width * right2[1];
8711 vert[11] = org2[2] + width * right2[2];
8714 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)
8716 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8717 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8718 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8719 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8720 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8721 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8722 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8723 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8724 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8725 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8726 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8727 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8730 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8735 VectorSet(v, x, y, z);
8736 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8737 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8739 if (i == mesh->numvertices)
8741 if (mesh->numvertices < mesh->maxvertices)
8743 VectorCopy(v, vertex3f);
8744 mesh->numvertices++;
8746 return mesh->numvertices;
8752 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8756 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8757 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8758 e = mesh->element3i + mesh->numtriangles * 3;
8759 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8761 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8762 if (mesh->numtriangles < mesh->maxtriangles)
8767 mesh->numtriangles++;
8769 element[1] = element[2];
8773 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8777 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8778 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8779 e = mesh->element3i + mesh->numtriangles * 3;
8780 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8782 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8783 if (mesh->numtriangles < mesh->maxtriangles)
8788 mesh->numtriangles++;
8790 element[1] = element[2];
8794 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8795 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8797 int planenum, planenum2;
8800 mplane_t *plane, *plane2;
8802 double temppoints[2][256*3];
8803 // figure out how large a bounding box we need to properly compute this brush
8805 for (w = 0;w < numplanes;w++)
8806 maxdist = max(maxdist, fabs(planes[w].dist));
8807 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8808 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8809 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8813 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8814 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8816 if (planenum2 == planenum)
8818 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);
8821 if (tempnumpoints < 3)
8823 // generate elements forming a triangle fan for this polygon
8824 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8828 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)
8830 texturelayer_t *layer;
8831 layer = t->currentlayers + t->currentnumlayers++;
8833 layer->depthmask = depthmask;
8834 layer->blendfunc1 = blendfunc1;
8835 layer->blendfunc2 = blendfunc2;
8836 layer->texture = texture;
8837 layer->texmatrix = *matrix;
8838 layer->color[0] = r;
8839 layer->color[1] = g;
8840 layer->color[2] = b;
8841 layer->color[3] = a;
8844 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8847 index = parms[2] + r_refdef.scene.time * parms[3];
8848 index -= floor(index);
8852 case Q3WAVEFUNC_NONE:
8853 case Q3WAVEFUNC_NOISE:
8854 case Q3WAVEFUNC_COUNT:
8857 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8858 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8859 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8860 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8861 case Q3WAVEFUNC_TRIANGLE:
8863 f = index - floor(index);
8874 return (float)(parms[0] + parms[1] * f);
8877 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8882 matrix4x4_t matrix, temp;
8883 switch(tcmod->tcmod)
8887 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8888 matrix = r_waterscrollmatrix;
8890 matrix = identitymatrix;
8892 case Q3TCMOD_ENTITYTRANSLATE:
8893 // this is used in Q3 to allow the gamecode to control texcoord
8894 // scrolling on the entity, which is not supported in darkplaces yet.
8895 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8897 case Q3TCMOD_ROTATE:
8898 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8899 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8900 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8903 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8905 case Q3TCMOD_SCROLL:
8906 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8908 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8909 w = (int) tcmod->parms[0];
8910 h = (int) tcmod->parms[1];
8911 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8913 idx = (int) floor(f * w * h);
8914 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8916 case Q3TCMOD_STRETCH:
8917 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8918 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8920 case Q3TCMOD_TRANSFORM:
8921 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8922 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8923 VectorSet(tcmat + 6, 0 , 0 , 1);
8924 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8925 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8927 case Q3TCMOD_TURBULENT:
8928 // this is handled in the RSurf_PrepareVertices function
8929 matrix = identitymatrix;
8933 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8936 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8938 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8939 char name[MAX_QPATH];
8940 skinframe_t *skinframe;
8941 unsigned char pixels[296*194];
8942 strlcpy(cache->name, skinname, sizeof(cache->name));
8943 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8944 if (developer_loading.integer)
8945 Con_Printf("loading %s\n", name);
8946 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8947 if (!skinframe || !skinframe->base)
8950 fs_offset_t filesize;
8952 f = FS_LoadFile(name, tempmempool, true, &filesize);
8955 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8956 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8960 cache->skinframe = skinframe;
8963 texture_t *R_GetCurrentTexture(texture_t *t)
8966 const entity_render_t *ent = rsurface.entity;
8967 dp_model_t *model = ent->model;
8968 q3shaderinfo_layer_tcmod_t *tcmod;
8970 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8971 return t->currentframe;
8972 t->update_lastrenderframe = r_textureframe;
8973 t->update_lastrenderentity = (void *)ent;
8975 // switch to an alternate material if this is a q1bsp animated material
8977 texture_t *texture = t;
8978 int s = rsurface.ent_skinnum;
8979 if ((unsigned int)s >= (unsigned int)model->numskins)
8981 if (model->skinscenes)
8983 if (model->skinscenes[s].framecount > 1)
8984 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8986 s = model->skinscenes[s].firstframe;
8989 t = t + s * model->num_surfaces;
8992 // use an alternate animation if the entity's frame is not 0,
8993 // and only if the texture has an alternate animation
8994 if (rsurface.ent_alttextures && t->anim_total[1])
8995 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8997 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8999 texture->currentframe = t;
9002 // update currentskinframe to be a qw skin or animation frame
9003 if (rsurface.ent_qwskin >= 0)
9005 i = rsurface.ent_qwskin;
9006 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9008 r_qwskincache_size = cl.maxclients;
9010 Mem_Free(r_qwskincache);
9011 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9013 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9014 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9015 t->currentskinframe = r_qwskincache[i].skinframe;
9016 if (t->currentskinframe == NULL)
9017 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9019 else if (t->numskinframes >= 2)
9020 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9021 if (t->backgroundnumskinframes >= 2)
9022 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9024 t->currentmaterialflags = t->basematerialflags;
9025 t->currentalpha = rsurface.colormod[3];
9026 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9027 t->currentalpha *= r_wateralpha.value;
9028 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9029 t->currentalpha *= t->r_water_wateralpha;
9030 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9031 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9032 if (!(rsurface.ent_flags & RENDER_LIGHT))
9033 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9034 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9036 // pick a model lighting mode
9037 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9038 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9040 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9042 if (rsurface.ent_flags & RENDER_ADDITIVE)
9043 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9044 else if (t->currentalpha < 1)
9045 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9046 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9047 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9048 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9049 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9050 if (t->backgroundnumskinframes)
9051 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9052 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9054 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9055 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9058 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9059 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9060 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9062 // there is no tcmod
9063 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9065 t->currenttexmatrix = r_waterscrollmatrix;
9066 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9068 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9070 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9071 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9074 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9075 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9076 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9077 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9079 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9080 if (t->currentskinframe->qpixels)
9081 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9082 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9083 if (!t->basetexture)
9084 t->basetexture = r_texture_notexture;
9085 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9086 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9087 t->nmaptexture = t->currentskinframe->nmap;
9088 if (!t->nmaptexture)
9089 t->nmaptexture = r_texture_blanknormalmap;
9090 t->glosstexture = r_texture_black;
9091 t->glowtexture = t->currentskinframe->glow;
9092 t->fogtexture = t->currentskinframe->fog;
9093 t->reflectmasktexture = t->currentskinframe->reflect;
9094 if (t->backgroundnumskinframes)
9096 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9097 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9098 t->backgroundglosstexture = r_texture_black;
9099 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9100 if (!t->backgroundnmaptexture)
9101 t->backgroundnmaptexture = r_texture_blanknormalmap;
9105 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9106 t->backgroundnmaptexture = r_texture_blanknormalmap;
9107 t->backgroundglosstexture = r_texture_black;
9108 t->backgroundglowtexture = NULL;
9110 t->specularpower = r_shadow_glossexponent.value;
9111 // TODO: store reference values for these in the texture?
9112 t->specularscale = 0;
9113 if (r_shadow_gloss.integer > 0)
9115 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9117 if (r_shadow_glossintensity.value > 0)
9119 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9120 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9121 t->specularscale = r_shadow_glossintensity.value;
9124 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9126 t->glosstexture = r_texture_white;
9127 t->backgroundglosstexture = r_texture_white;
9128 t->specularscale = r_shadow_gloss2intensity.value;
9129 t->specularpower = r_shadow_gloss2exponent.value;
9132 t->specularscale *= t->specularscalemod;
9133 t->specularpower *= t->specularpowermod;
9135 // lightmaps mode looks bad with dlights using actual texturing, so turn
9136 // off the colormap and glossmap, but leave the normalmap on as it still
9137 // accurately represents the shading involved
9138 if (gl_lightmaps.integer)
9140 t->basetexture = r_texture_grey128;
9141 t->pantstexture = r_texture_black;
9142 t->shirttexture = r_texture_black;
9143 t->nmaptexture = r_texture_blanknormalmap;
9144 t->glosstexture = r_texture_black;
9145 t->glowtexture = NULL;
9146 t->fogtexture = NULL;
9147 t->reflectmasktexture = NULL;
9148 t->backgroundbasetexture = NULL;
9149 t->backgroundnmaptexture = r_texture_blanknormalmap;
9150 t->backgroundglosstexture = r_texture_black;
9151 t->backgroundglowtexture = NULL;
9152 t->specularscale = 0;
9153 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9156 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9157 VectorClear(t->dlightcolor);
9158 t->currentnumlayers = 0;
9159 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9161 int blendfunc1, blendfunc2;
9163 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9165 blendfunc1 = GL_SRC_ALPHA;
9166 blendfunc2 = GL_ONE;
9168 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9170 blendfunc1 = GL_SRC_ALPHA;
9171 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9173 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9175 blendfunc1 = t->customblendfunc[0];
9176 blendfunc2 = t->customblendfunc[1];
9180 blendfunc1 = GL_ONE;
9181 blendfunc2 = GL_ZERO;
9183 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9184 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9186 // fullbright is not affected by r_refdef.lightmapintensity
9187 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]);
9188 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9189 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]);
9190 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9191 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]);
9195 vec3_t ambientcolor;
9197 // set the color tint used for lights affecting this surface
9198 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9200 // q3bsp has no lightmap updates, so the lightstylevalue that
9201 // would normally be baked into the lightmap must be
9202 // applied to the color
9203 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9204 if (model->type == mod_brushq3)
9205 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9206 colorscale *= r_refdef.lightmapintensity;
9207 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9208 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9209 // basic lit geometry
9210 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]);
9211 // add pants/shirt if needed
9212 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9213 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]);
9214 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9215 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]);
9216 // now add ambient passes if needed
9217 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9219 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]);
9220 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9221 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]);
9222 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9223 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]);
9226 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9227 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]);
9228 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9230 // if this is opaque use alpha blend which will darken the earlier
9233 // if this is an alpha blended material, all the earlier passes
9234 // were darkened by fog already, so we only need to add the fog
9235 // color ontop through the fog mask texture
9237 // if this is an additive blended material, all the earlier passes
9238 // were darkened by fog already, and we should not add fog color
9239 // (because the background was not darkened, there is no fog color
9240 // that was lost behind it).
9241 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]);
9245 return t->currentframe;
9248 rsurfacestate_t rsurface;
9250 void R_Mesh_ResizeArrays(int newvertices)
9253 if (rsurface.array_size >= newvertices)
9255 if (rsurface.array_modelvertex3f)
9256 Mem_Free(rsurface.array_modelvertex3f);
9257 rsurface.array_size = (newvertices + 1023) & ~1023;
9258 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9259 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9260 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9261 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9262 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9263 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9264 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9265 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9266 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9267 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9268 rsurface.array_color4f = base + rsurface.array_size * 27;
9269 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9272 void RSurf_ActiveWorldEntity(void)
9274 dp_model_t *model = r_refdef.scene.worldmodel;
9275 //if (rsurface.entity == r_refdef.scene.worldentity)
9277 rsurface.entity = r_refdef.scene.worldentity;
9278 rsurface.skeleton = NULL;
9279 rsurface.ent_skinnum = 0;
9280 rsurface.ent_qwskin = -1;
9281 rsurface.ent_shadertime = 0;
9282 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9283 if (rsurface.array_size < model->surfmesh.num_vertices)
9284 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9285 rsurface.matrix = identitymatrix;
9286 rsurface.inversematrix = identitymatrix;
9287 rsurface.matrixscale = 1;
9288 rsurface.inversematrixscale = 1;
9289 R_EntityMatrix(&identitymatrix);
9290 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9291 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9292 rsurface.fograngerecip = r_refdef.fograngerecip;
9293 rsurface.fogheightfade = r_refdef.fogheightfade;
9294 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9295 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9296 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9297 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9298 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9299 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9300 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9301 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9302 rsurface.colormod[3] = 1;
9303 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);
9304 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9305 rsurface.frameblend[0].lerp = 1;
9306 rsurface.ent_alttextures = false;
9307 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9308 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9309 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9310 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9311 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9312 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9313 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9314 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9315 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9316 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9317 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9318 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9319 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9320 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9321 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9322 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9323 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9324 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9325 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9326 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9327 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9328 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9329 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9330 rsurface.modelelement3i = model->surfmesh.data_element3i;
9331 rsurface.modelelement3s = model->surfmesh.data_element3s;
9332 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9333 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9334 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9335 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9336 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9337 rsurface.modelsurfaces = model->data_surfaces;
9338 rsurface.generatedvertex = false;
9339 rsurface.vertex3f = rsurface.modelvertex3f;
9340 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9341 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9342 rsurface.svector3f = rsurface.modelsvector3f;
9343 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9344 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9345 rsurface.tvector3f = rsurface.modeltvector3f;
9346 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9347 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9348 rsurface.normal3f = rsurface.modelnormal3f;
9349 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9350 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9351 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9354 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9356 dp_model_t *model = ent->model;
9357 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9359 rsurface.entity = (entity_render_t *)ent;
9360 rsurface.skeleton = ent->skeleton;
9361 rsurface.ent_skinnum = ent->skinnum;
9362 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;
9363 rsurface.ent_shadertime = ent->shadertime;
9364 rsurface.ent_flags = ent->flags;
9365 if (rsurface.array_size < model->surfmesh.num_vertices)
9366 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9367 rsurface.matrix = ent->matrix;
9368 rsurface.inversematrix = ent->inversematrix;
9369 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9370 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9371 R_EntityMatrix(&rsurface.matrix);
9372 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9373 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9374 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9375 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9376 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9377 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9378 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9379 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9380 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9381 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9382 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9383 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9384 rsurface.colormod[3] = ent->alpha;
9385 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9386 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9387 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9388 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9389 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9390 if (ent->model->brush.submodel && !prepass)
9392 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9393 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9395 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9397 if (ent->animcache_vertex3f && !r_framedata_failed)
9399 rsurface.modelvertex3f = ent->animcache_vertex3f;
9400 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9401 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9402 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9404 else if (wanttangents)
9406 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9407 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9408 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9409 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9410 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9412 else if (wantnormals)
9414 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9415 rsurface.modelsvector3f = NULL;
9416 rsurface.modeltvector3f = NULL;
9417 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9418 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9422 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9423 rsurface.modelsvector3f = NULL;
9424 rsurface.modeltvector3f = NULL;
9425 rsurface.modelnormal3f = NULL;
9426 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9428 rsurface.modelvertex3f_bufferobject = 0;
9429 rsurface.modelvertex3f_bufferoffset = 0;
9430 rsurface.modelsvector3f_bufferobject = 0;
9431 rsurface.modelsvector3f_bufferoffset = 0;
9432 rsurface.modeltvector3f_bufferobject = 0;
9433 rsurface.modeltvector3f_bufferoffset = 0;
9434 rsurface.modelnormal3f_bufferobject = 0;
9435 rsurface.modelnormal3f_bufferoffset = 0;
9436 rsurface.generatedvertex = true;
9440 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9441 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9442 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9443 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9444 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9445 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9446 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9447 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9448 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9449 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9450 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9451 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9452 rsurface.generatedvertex = false;
9454 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9455 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9456 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9457 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9458 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9459 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9460 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9461 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9462 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9463 rsurface.modelelement3i = model->surfmesh.data_element3i;
9464 rsurface.modelelement3s = model->surfmesh.data_element3s;
9465 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9466 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9467 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9468 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9469 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9470 rsurface.modelsurfaces = model->data_surfaces;
9471 rsurface.vertex3f = rsurface.modelvertex3f;
9472 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9473 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9474 rsurface.svector3f = rsurface.modelsvector3f;
9475 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9476 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9477 rsurface.tvector3f = rsurface.modeltvector3f;
9478 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9479 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9480 rsurface.normal3f = rsurface.modelnormal3f;
9481 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9482 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9483 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9486 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)
9488 rsurface.entity = r_refdef.scene.worldentity;
9489 rsurface.skeleton = NULL;
9490 rsurface.ent_skinnum = 0;
9491 rsurface.ent_qwskin = -1;
9492 rsurface.ent_shadertime = shadertime;
9493 rsurface.ent_flags = entflags;
9494 rsurface.modelnum_vertices = numvertices;
9495 rsurface.modelnum_triangles = numtriangles;
9496 if (rsurface.array_size < rsurface.modelnum_vertices)
9497 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9498 rsurface.matrix = *matrix;
9499 rsurface.inversematrix = *inversematrix;
9500 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9501 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9502 R_EntityMatrix(&rsurface.matrix);
9503 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9504 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9505 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9506 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9507 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9508 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9509 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9510 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9511 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9512 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9513 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9514 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9515 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);
9516 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9517 rsurface.frameblend[0].lerp = 1;
9518 rsurface.ent_alttextures = false;
9519 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9520 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9523 rsurface.modelvertex3f = vertex3f;
9524 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9525 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9526 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9528 else if (wantnormals)
9530 rsurface.modelvertex3f = vertex3f;
9531 rsurface.modelsvector3f = NULL;
9532 rsurface.modeltvector3f = NULL;
9533 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9537 rsurface.modelvertex3f = vertex3f;
9538 rsurface.modelsvector3f = NULL;
9539 rsurface.modeltvector3f = NULL;
9540 rsurface.modelnormal3f = NULL;
9542 rsurface.modelvertex3f_bufferobject = 0;
9543 rsurface.modelvertex3f_bufferoffset = 0;
9544 rsurface.modelsvector3f_bufferobject = 0;
9545 rsurface.modelsvector3f_bufferoffset = 0;
9546 rsurface.modeltvector3f_bufferobject = 0;
9547 rsurface.modeltvector3f_bufferoffset = 0;
9548 rsurface.modelnormal3f_bufferobject = 0;
9549 rsurface.modelnormal3f_bufferoffset = 0;
9550 rsurface.generatedvertex = true;
9551 rsurface.modellightmapcolor4f = color4f;
9552 rsurface.modellightmapcolor4f_bufferobject = 0;
9553 rsurface.modellightmapcolor4f_bufferoffset = 0;
9554 rsurface.modeltexcoordtexture2f = texcoord2f;
9555 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9556 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9557 rsurface.modeltexcoordlightmap2f = NULL;
9558 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9559 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9560 rsurface.modelelement3i = element3i;
9561 rsurface.modelelement3s = element3s;
9562 rsurface.modelelement3i_bufferobject = 0;
9563 rsurface.modelelement3s_bufferobject = 0;
9564 rsurface.modellightmapoffsets = NULL;
9565 rsurface.modelsurfaces = NULL;
9566 rsurface.vertex3f = rsurface.modelvertex3f;
9567 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9568 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9569 rsurface.svector3f = rsurface.modelsvector3f;
9570 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9571 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9572 rsurface.tvector3f = rsurface.modeltvector3f;
9573 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9574 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9575 rsurface.normal3f = rsurface.modelnormal3f;
9576 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9577 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9578 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9580 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9582 if ((wantnormals || wanttangents) && !normal3f)
9583 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9584 if (wanttangents && !svector3f)
9585 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);
9589 float RSurf_FogPoint(const float *v)
9591 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9592 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9593 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9594 float FogHeightFade = r_refdef.fogheightfade;
9596 unsigned int fogmasktableindex;
9597 if (r_refdef.fogplaneviewabove)
9598 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9600 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9601 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9602 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9605 float RSurf_FogVertex(const float *v)
9607 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9608 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9609 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9610 float FogHeightFade = rsurface.fogheightfade;
9612 unsigned int fogmasktableindex;
9613 if (r_refdef.fogplaneviewabove)
9614 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9616 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9617 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9618 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9621 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9622 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9625 int texturesurfaceindex;
9630 const float *v1, *in_tc;
9632 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9634 q3shaderinfo_deform_t *deform;
9635 // 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
9636 if (rsurface.generatedvertex)
9638 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9639 generatenormals = true;
9640 for (i = 0;i < Q3MAXDEFORMS;i++)
9642 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9644 generatetangents = true;
9645 generatenormals = true;
9647 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9648 generatenormals = true;
9650 if (generatenormals && !rsurface.modelnormal3f)
9652 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9653 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9654 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9655 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9657 if (generatetangents && !rsurface.modelsvector3f)
9659 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9660 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9661 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9662 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9663 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9664 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9665 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);
9668 rsurface.vertex3f = rsurface.modelvertex3f;
9669 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9670 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9671 rsurface.svector3f = rsurface.modelsvector3f;
9672 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9673 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9674 rsurface.tvector3f = rsurface.modeltvector3f;
9675 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9676 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9677 rsurface.normal3f = rsurface.modelnormal3f;
9678 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9679 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9680 // if vertices are deformed (sprite flares and things in maps, possibly
9681 // water waves, bulges and other deformations), generate them into
9682 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9683 // (may be static model data or generated data for an animated model, or
9684 // the previous deform pass)
9685 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9687 switch (deform->deform)
9690 case Q3DEFORM_PROJECTIONSHADOW:
9691 case Q3DEFORM_TEXT0:
9692 case Q3DEFORM_TEXT1:
9693 case Q3DEFORM_TEXT2:
9694 case Q3DEFORM_TEXT3:
9695 case Q3DEFORM_TEXT4:
9696 case Q3DEFORM_TEXT5:
9697 case Q3DEFORM_TEXT6:
9698 case Q3DEFORM_TEXT7:
9701 case Q3DEFORM_AUTOSPRITE:
9702 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9703 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9704 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9705 VectorNormalize(newforward);
9706 VectorNormalize(newright);
9707 VectorNormalize(newup);
9708 // make deformed versions of only the model vertices used by the specified surfaces
9709 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9711 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9712 // a single autosprite surface can contain multiple sprites...
9713 for (j = 0;j < surface->num_vertices - 3;j += 4)
9715 VectorClear(center);
9716 for (i = 0;i < 4;i++)
9717 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9718 VectorScale(center, 0.25f, center);
9719 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9720 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9721 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9722 for (i = 0;i < 4;i++)
9724 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9725 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9728 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);
9729 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);
9731 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9732 rsurface.vertex3f_bufferobject = 0;
9733 rsurface.vertex3f_bufferoffset = 0;
9734 rsurface.svector3f = rsurface.array_deformedsvector3f;
9735 rsurface.svector3f_bufferobject = 0;
9736 rsurface.svector3f_bufferoffset = 0;
9737 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9738 rsurface.tvector3f_bufferobject = 0;
9739 rsurface.tvector3f_bufferoffset = 0;
9740 rsurface.normal3f = rsurface.array_deformednormal3f;
9741 rsurface.normal3f_bufferobject = 0;
9742 rsurface.normal3f_bufferoffset = 0;
9744 case Q3DEFORM_AUTOSPRITE2:
9745 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9746 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9747 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9748 VectorNormalize(newforward);
9749 VectorNormalize(newright);
9750 VectorNormalize(newup);
9751 // make deformed versions of only the model vertices used by the specified surfaces
9752 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9754 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9755 const float *v1, *v2;
9765 memset(shortest, 0, sizeof(shortest));
9766 // a single autosprite surface can contain multiple sprites...
9767 for (j = 0;j < surface->num_vertices - 3;j += 4)
9769 VectorClear(center);
9770 for (i = 0;i < 4;i++)
9771 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9772 VectorScale(center, 0.25f, center);
9773 // find the two shortest edges, then use them to define the
9774 // axis vectors for rotating around the central axis
9775 for (i = 0;i < 6;i++)
9777 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9778 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9780 Debug_PolygonBegin(NULL, 0);
9781 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9782 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);
9783 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9786 l = VectorDistance2(v1, v2);
9787 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9789 l += (1.0f / 1024.0f);
9790 if (shortest[0].length2 > l || i == 0)
9792 shortest[1] = shortest[0];
9793 shortest[0].length2 = l;
9794 shortest[0].v1 = v1;
9795 shortest[0].v2 = v2;
9797 else if (shortest[1].length2 > l || i == 1)
9799 shortest[1].length2 = l;
9800 shortest[1].v1 = v1;
9801 shortest[1].v2 = v2;
9804 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9805 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9807 Debug_PolygonBegin(NULL, 0);
9808 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9809 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);
9810 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9813 // this calculates the right vector from the shortest edge
9814 // and the up vector from the edge midpoints
9815 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9816 VectorNormalize(right);
9817 VectorSubtract(end, start, up);
9818 VectorNormalize(up);
9819 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9820 VectorSubtract(rsurface.localvieworigin, center, forward);
9821 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9822 VectorNegate(forward, forward);
9823 VectorReflect(forward, 0, up, forward);
9824 VectorNormalize(forward);
9825 CrossProduct(up, forward, newright);
9826 VectorNormalize(newright);
9828 Debug_PolygonBegin(NULL, 0);
9829 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);
9830 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9831 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9835 Debug_PolygonBegin(NULL, 0);
9836 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9837 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9838 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9841 // rotate the quad around the up axis vector, this is made
9842 // especially easy by the fact we know the quad is flat,
9843 // so we only have to subtract the center position and
9844 // measure distance along the right vector, and then
9845 // multiply that by the newright vector and add back the
9847 // we also need to subtract the old position to undo the
9848 // displacement from the center, which we do with a
9849 // DotProduct, the subtraction/addition of center is also
9850 // optimized into DotProducts here
9851 l = DotProduct(right, center);
9852 for (i = 0;i < 4;i++)
9854 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9855 f = DotProduct(right, v1) - l;
9856 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9859 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);
9860 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);
9862 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9863 rsurface.vertex3f_bufferobject = 0;
9864 rsurface.vertex3f_bufferoffset = 0;
9865 rsurface.svector3f = rsurface.array_deformedsvector3f;
9866 rsurface.svector3f_bufferobject = 0;
9867 rsurface.svector3f_bufferoffset = 0;
9868 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9869 rsurface.tvector3f_bufferobject = 0;
9870 rsurface.tvector3f_bufferoffset = 0;
9871 rsurface.normal3f = rsurface.array_deformednormal3f;
9872 rsurface.normal3f_bufferobject = 0;
9873 rsurface.normal3f_bufferoffset = 0;
9875 case Q3DEFORM_NORMAL:
9876 // deform the normals to make reflections wavey
9877 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9879 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9880 for (j = 0;j < surface->num_vertices;j++)
9883 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9884 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9885 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9886 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9887 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9888 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9889 VectorNormalize(normal);
9891 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);
9893 rsurface.svector3f = rsurface.array_deformedsvector3f;
9894 rsurface.svector3f_bufferobject = 0;
9895 rsurface.svector3f_bufferoffset = 0;
9896 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9897 rsurface.tvector3f_bufferobject = 0;
9898 rsurface.tvector3f_bufferoffset = 0;
9899 rsurface.normal3f = rsurface.array_deformednormal3f;
9900 rsurface.normal3f_bufferobject = 0;
9901 rsurface.normal3f_bufferoffset = 0;
9904 // deform vertex array to make wavey water and flags and such
9905 waveparms[0] = deform->waveparms[0];
9906 waveparms[1] = deform->waveparms[1];
9907 waveparms[2] = deform->waveparms[2];
9908 waveparms[3] = deform->waveparms[3];
9909 // this is how a divisor of vertex influence on deformation
9910 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9911 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9914 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9915 for (j = 0;j < surface->num_vertices;j++)
9917 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9918 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9919 // if the wavefunc depends on time, evaluate it per-vertex
9922 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9923 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9925 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9928 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9929 rsurface.vertex3f_bufferobject = 0;
9930 rsurface.vertex3f_bufferoffset = 0;
9932 case Q3DEFORM_BULGE:
9933 // deform vertex array to make the surface have moving bulges
9934 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9936 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9937 for (j = 0;j < surface->num_vertices;j++)
9939 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9940 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9943 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9944 rsurface.vertex3f_bufferobject = 0;
9945 rsurface.vertex3f_bufferoffset = 0;
9948 // deform vertex array
9949 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9950 VectorScale(deform->parms, scale, waveparms);
9951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9953 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9954 for (j = 0;j < surface->num_vertices;j++)
9955 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9957 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9958 rsurface.vertex3f_bufferobject = 0;
9959 rsurface.vertex3f_bufferoffset = 0;
9963 // generate texcoords based on the chosen texcoord source
9964 switch(rsurface.texture->tcgen.tcgen)
9967 case Q3TCGEN_TEXTURE:
9968 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9969 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9970 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9972 case Q3TCGEN_LIGHTMAP:
9973 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9974 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9975 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9977 case Q3TCGEN_VECTOR:
9978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9980 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9981 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)
9983 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9984 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9987 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9988 rsurface.texcoordtexture2f_bufferobject = 0;
9989 rsurface.texcoordtexture2f_bufferoffset = 0;
9991 case Q3TCGEN_ENVIRONMENT:
9992 // make environment reflections using a spheremap
9993 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9995 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9996 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9997 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9998 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9999 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10001 // identical to Q3A's method, but executed in worldspace so
10002 // carried models can be shiny too
10004 float viewer[3], d, reflected[3], worldreflected[3];
10006 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10007 // VectorNormalize(viewer);
10009 d = DotProduct(normal, viewer);
10011 reflected[0] = normal[0]*2*d - viewer[0];
10012 reflected[1] = normal[1]*2*d - viewer[1];
10013 reflected[2] = normal[2]*2*d - viewer[2];
10014 // note: this is proportinal to viewer, so we can normalize later
10016 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10017 VectorNormalize(worldreflected);
10019 // note: this sphere map only uses world x and z!
10020 // so positive and negative y will LOOK THE SAME.
10021 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10022 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10025 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10026 rsurface.texcoordtexture2f_bufferobject = 0;
10027 rsurface.texcoordtexture2f_bufferoffset = 0;
10030 // the only tcmod that needs software vertex processing is turbulent, so
10031 // check for it here and apply the changes if needed
10032 // and we only support that as the first one
10033 // (handling a mixture of turbulent and other tcmods would be problematic
10034 // without punting it entirely to a software path)
10035 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10037 amplitude = rsurface.texture->tcmods[0].parms[1];
10038 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10041 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10042 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)
10044 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10045 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10048 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10049 rsurface.texcoordtexture2f_bufferobject = 0;
10050 rsurface.texcoordtexture2f_bufferoffset = 0;
10052 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10053 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10054 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10055 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10058 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10061 const msurface_t *surface = texturesurfacelist[0];
10062 const msurface_t *surface2;
10067 // TODO: lock all array ranges before render, rather than on each surface
10068 if (texturenumsurfaces == 1)
10069 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);
10070 else if (r_batchmode.integer == 2)
10072 #define MAXBATCHTRIANGLES 4096
10073 int batchtriangles = 0;
10074 static int batchelements[MAXBATCHTRIANGLES*3];
10075 for (i = 0;i < texturenumsurfaces;i = j)
10077 surface = texturesurfacelist[i];
10079 if (surface->num_triangles > MAXBATCHTRIANGLES)
10081 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);
10084 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10085 batchtriangles = surface->num_triangles;
10086 firstvertex = surface->num_firstvertex;
10087 endvertex = surface->num_firstvertex + surface->num_vertices;
10088 for (;j < texturenumsurfaces;j++)
10090 surface2 = texturesurfacelist[j];
10091 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10093 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10094 batchtriangles += surface2->num_triangles;
10095 firstvertex = min(firstvertex, surface2->num_firstvertex);
10096 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10098 surface2 = texturesurfacelist[j-1];
10099 numvertices = endvertex - firstvertex;
10100 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10103 else if (r_batchmode.integer == 1)
10105 for (i = 0;i < texturenumsurfaces;i = j)
10107 surface = texturesurfacelist[i];
10108 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10109 if (texturesurfacelist[j] != surface2)
10111 surface2 = texturesurfacelist[j-1];
10112 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10113 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10114 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10119 for (i = 0;i < texturenumsurfaces;i++)
10121 surface = texturesurfacelist[i];
10122 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);
10127 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10129 switch(vid.renderpath)
10131 case RENDERPATH_CGGL:
10133 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10134 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10137 case RENDERPATH_GL20:
10138 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10139 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10141 case RENDERPATH_GL13:
10142 case RENDERPATH_GL11:
10143 R_Mesh_TexBind(0, surface->lightmaptexture);
10148 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10150 // pick the closest matching water plane and bind textures
10151 int planeindex, vertexindex;
10155 r_waterstate_waterplane_t *p, *bestp;
10158 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10161 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10163 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10164 d += fabs(PlaneDiff(vert, &p->plane));
10166 if (bestd > d || !bestp)
10172 switch(vid.renderpath)
10174 case RENDERPATH_CGGL:
10176 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10177 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10180 case RENDERPATH_GL20:
10181 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10182 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10184 case RENDERPATH_GL13:
10185 case RENDERPATH_GL11:
10190 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10193 const msurface_t *surface;
10194 if (r_waterstate.renderingscene)
10196 for (i = 0;i < texturenumsurfaces;i++)
10198 surface = texturesurfacelist[i];
10199 RSurf_BindLightmapForSurface(surface);
10200 RSurf_BindReflectionForSurface(surface);
10201 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);
10205 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10209 const msurface_t *surface = texturesurfacelist[0];
10210 const msurface_t *surface2;
10215 if (texturenumsurfaces == 1)
10217 RSurf_BindLightmapForSurface(surface);
10218 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);
10220 else if (r_batchmode.integer == 2)
10222 #define MAXBATCHTRIANGLES 4096
10223 int batchtriangles = 0;
10224 static int batchelements[MAXBATCHTRIANGLES*3];
10225 for (i = 0;i < texturenumsurfaces;i = j)
10227 surface = texturesurfacelist[i];
10228 RSurf_BindLightmapForSurface(surface);
10230 if (surface->num_triangles > MAXBATCHTRIANGLES)
10232 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);
10235 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10236 batchtriangles = surface->num_triangles;
10237 firstvertex = surface->num_firstvertex;
10238 endvertex = surface->num_firstvertex + surface->num_vertices;
10239 for (;j < texturenumsurfaces;j++)
10241 surface2 = texturesurfacelist[j];
10242 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10244 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10245 batchtriangles += surface2->num_triangles;
10246 firstvertex = min(firstvertex, surface2->num_firstvertex);
10247 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10249 surface2 = texturesurfacelist[j-1];
10250 numvertices = endvertex - firstvertex;
10251 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10254 else if (r_batchmode.integer == 1)
10257 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10258 for (i = 0;i < texturenumsurfaces;i = j)
10260 surface = texturesurfacelist[i];
10261 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10262 if (texturesurfacelist[j] != surface2)
10264 Con_Printf(" %i", j - i);
10267 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10269 for (i = 0;i < texturenumsurfaces;i = j)
10271 surface = texturesurfacelist[i];
10272 RSurf_BindLightmapForSurface(surface);
10273 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10274 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10277 Con_Printf(" %i", j - i);
10279 surface2 = texturesurfacelist[j-1];
10280 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10281 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10282 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10290 for (i = 0;i < texturenumsurfaces;i++)
10292 surface = texturesurfacelist[i];
10293 RSurf_BindLightmapForSurface(surface);
10294 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);
10299 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10302 int texturesurfaceindex;
10303 if (r_showsurfaces.integer == 2)
10305 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10307 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10308 for (j = 0;j < surface->num_triangles;j++)
10310 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10311 GL_Color(f, f, f, 1);
10312 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10318 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10320 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10321 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10322 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);
10323 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);
10328 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10330 int texturesurfaceindex;
10334 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10336 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10337 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)
10345 rsurface.lightmapcolor4f = rsurface.array_color4f;
10346 rsurface.lightmapcolor4f_bufferobject = 0;
10347 rsurface.lightmapcolor4f_bufferoffset = 0;
10350 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10352 int texturesurfaceindex;
10358 if (rsurface.lightmapcolor4f)
10360 // generate color arrays for the surfaces in this list
10361 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10363 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10364 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)
10366 f = RSurf_FogVertex(v);
10376 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10378 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10379 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)
10381 f = RSurf_FogVertex(v);
10389 rsurface.lightmapcolor4f = rsurface.array_color4f;
10390 rsurface.lightmapcolor4f_bufferobject = 0;
10391 rsurface.lightmapcolor4f_bufferoffset = 0;
10394 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(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);
10411 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10412 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10413 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10417 rsurface.lightmapcolor4f = rsurface.array_color4f;
10418 rsurface.lightmapcolor4f_bufferobject = 0;
10419 rsurface.lightmapcolor4f_bufferoffset = 0;
10422 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10424 int texturesurfaceindex;
10428 if (!rsurface.lightmapcolor4f)
10430 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10432 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10433 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)
10441 rsurface.lightmapcolor4f = rsurface.array_color4f;
10442 rsurface.lightmapcolor4f_bufferobject = 0;
10443 rsurface.lightmapcolor4f_bufferoffset = 0;
10446 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10448 int texturesurfaceindex;
10452 if (!rsurface.lightmapcolor4f)
10454 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10456 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10457 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)
10459 c2[0] = c[0] + r_refdef.scene.ambient;
10460 c2[1] = c[1] + r_refdef.scene.ambient;
10461 c2[2] = c[2] + r_refdef.scene.ambient;
10465 rsurface.lightmapcolor4f = rsurface.array_color4f;
10466 rsurface.lightmapcolor4f_bufferobject = 0;
10467 rsurface.lightmapcolor4f_bufferoffset = 0;
10470 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10473 rsurface.lightmapcolor4f = NULL;
10474 rsurface.lightmapcolor4f_bufferobject = 0;
10475 rsurface.lightmapcolor4f_bufferoffset = 0;
10476 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10477 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10478 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10479 GL_Color(r, g, b, a);
10480 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10483 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10485 // TODO: optimize applyfog && applycolor case
10486 // just apply fog if necessary, and tint the fog color array if necessary
10487 rsurface.lightmapcolor4f = NULL;
10488 rsurface.lightmapcolor4f_bufferobject = 0;
10489 rsurface.lightmapcolor4f_bufferoffset = 0;
10490 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10491 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10492 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10493 GL_Color(r, g, b, a);
10494 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10497 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10499 int texturesurfaceindex;
10503 if (texturesurfacelist[0]->lightmapinfo)
10505 // generate color arrays for the surfaces in this list
10506 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10508 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10509 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10511 if (surface->lightmapinfo->samples)
10513 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10514 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10515 VectorScale(lm, scale, c);
10516 if (surface->lightmapinfo->styles[1] != 255)
10518 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10520 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10521 VectorMA(c, scale, lm, c);
10522 if (surface->lightmapinfo->styles[2] != 255)
10525 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10526 VectorMA(c, scale, lm, c);
10527 if (surface->lightmapinfo->styles[3] != 255)
10530 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10531 VectorMA(c, scale, lm, c);
10541 rsurface.lightmapcolor4f = rsurface.array_color4f;
10542 rsurface.lightmapcolor4f_bufferobject = 0;
10543 rsurface.lightmapcolor4f_bufferoffset = 0;
10547 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10548 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10549 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10551 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10552 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10553 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10554 GL_Color(r, g, b, a);
10555 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10558 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10560 int texturesurfaceindex;
10567 vec3_t ambientcolor;
10568 vec3_t diffusecolor;
10572 VectorCopy(rsurface.modellight_lightdir, lightdir);
10573 f = 0.5f * r_refdef.lightmapintensity;
10574 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10575 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10576 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10577 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10578 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10579 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10581 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10583 // generate color arrays for the surfaces in this list
10584 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10586 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10587 int numverts = surface->num_vertices;
10588 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10589 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10590 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10591 // q3-style directional shading
10592 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10594 if ((f = DotProduct(n, lightdir)) > 0)
10595 VectorMA(ambientcolor, f, diffusecolor, c);
10597 VectorCopy(ambientcolor, c);
10605 rsurface.lightmapcolor4f = rsurface.array_color4f;
10606 rsurface.lightmapcolor4f_bufferobject = 0;
10607 rsurface.lightmapcolor4f_bufferoffset = 0;
10608 *applycolor = false;
10612 *r = ambientcolor[0];
10613 *g = ambientcolor[1];
10614 *b = ambientcolor[2];
10615 rsurface.lightmapcolor4f = NULL;
10616 rsurface.lightmapcolor4f_bufferobject = 0;
10617 rsurface.lightmapcolor4f_bufferoffset = 0;
10621 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10623 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10624 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10625 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10626 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10627 GL_Color(r, g, b, a);
10628 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10631 void RSurf_SetupDepthAndCulling(void)
10633 // submodels are biased to avoid z-fighting with world surfaces that they
10634 // may be exactly overlapping (avoids z-fighting artifacts on certain
10635 // doors and things in Quake maps)
10636 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10637 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10638 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10639 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10642 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10644 // transparent sky would be ridiculous
10645 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10647 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10648 skyrenderlater = true;
10649 RSurf_SetupDepthAndCulling();
10650 GL_DepthMask(true);
10651 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10652 // skymasking on them, and Quake3 never did sky masking (unlike
10653 // software Quake and software Quake2), so disable the sky masking
10654 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10655 // and skymasking also looks very bad when noclipping outside the
10656 // level, so don't use it then either.
10657 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10659 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10660 R_Mesh_ColorPointer(NULL, 0, 0);
10661 R_Mesh_ResetTextureState();
10662 if (skyrendermasked)
10664 R_SetupShader_DepthOrShadow();
10665 // depth-only (masking)
10666 GL_ColorMask(0,0,0,0);
10667 // just to make sure that braindead drivers don't draw
10668 // anything despite that colormask...
10669 GL_BlendFunc(GL_ZERO, GL_ONE);
10673 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10675 GL_BlendFunc(GL_ONE, GL_ZERO);
10677 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10678 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10679 if (skyrendermasked)
10680 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10682 R_Mesh_ResetTextureState();
10683 GL_Color(1, 1, 1, 1);
10686 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10687 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10688 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10690 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10692 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10695 // render screenspace normalmap to texture
10696 GL_DepthMask(true);
10697 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10698 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10700 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10702 // render water or distortion background, then blend surface on top
10703 GL_DepthMask(true);
10704 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10705 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10706 GL_DepthMask(false);
10707 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10708 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10709 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10711 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10715 // render surface normally
10716 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10717 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10718 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10719 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10720 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10721 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10723 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10727 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10729 // OpenGL 1.3 path - anything not completely ancient
10730 int texturesurfaceindex;
10731 qboolean applycolor;
10734 const texturelayer_t *layer;
10735 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10737 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10740 int layertexrgbscale;
10741 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10743 if (layerindex == 0)
10744 GL_AlphaTest(true);
10747 GL_AlphaTest(false);
10748 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10751 GL_DepthMask(layer->depthmask && writedepth);
10752 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10753 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10755 layertexrgbscale = 4;
10756 VectorScale(layer->color, 0.25f, layercolor);
10758 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10760 layertexrgbscale = 2;
10761 VectorScale(layer->color, 0.5f, layercolor);
10765 layertexrgbscale = 1;
10766 VectorScale(layer->color, 1.0f, layercolor);
10768 layercolor[3] = layer->color[3];
10769 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10770 R_Mesh_ColorPointer(NULL, 0, 0);
10771 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10772 switch (layer->type)
10774 case TEXTURELAYERTYPE_LITTEXTURE:
10775 // single-pass lightmapped texture with 2x rgbscale
10776 R_Mesh_TexBind(0, r_texture_white);
10777 R_Mesh_TexMatrix(0, NULL);
10778 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10779 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10780 R_Mesh_TexBind(1, layer->texture);
10781 R_Mesh_TexMatrix(1, &layer->texmatrix);
10782 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10783 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10784 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10785 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10786 else if (rsurface.uselightmaptexture)
10787 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10789 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10791 case TEXTURELAYERTYPE_TEXTURE:
10792 // singletexture unlit texture with transparency support
10793 R_Mesh_TexBind(0, layer->texture);
10794 R_Mesh_TexMatrix(0, &layer->texmatrix);
10795 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10796 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10797 R_Mesh_TexBind(1, 0);
10798 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10799 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10801 case TEXTURELAYERTYPE_FOG:
10802 // singletexture fogging
10803 if (layer->texture)
10805 R_Mesh_TexBind(0, layer->texture);
10806 R_Mesh_TexMatrix(0, &layer->texmatrix);
10807 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10808 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10812 R_Mesh_TexBind(0, 0);
10813 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10815 R_Mesh_TexBind(1, 0);
10816 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10817 // generate a color array for the fog pass
10818 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10819 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10825 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10826 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)
10828 f = 1 - RSurf_FogVertex(v);
10829 c[0] = layercolor[0];
10830 c[1] = layercolor[1];
10831 c[2] = layercolor[2];
10832 c[3] = f * layercolor[3];
10835 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10838 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10842 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10844 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10845 GL_AlphaTest(false);
10849 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10851 // OpenGL 1.1 - crusty old voodoo path
10852 int texturesurfaceindex;
10855 const texturelayer_t *layer;
10856 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10858 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10860 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10862 if (layerindex == 0)
10863 GL_AlphaTest(true);
10866 GL_AlphaTest(false);
10867 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10870 GL_DepthMask(layer->depthmask && writedepth);
10871 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10872 R_Mesh_ColorPointer(NULL, 0, 0);
10873 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10874 switch (layer->type)
10876 case TEXTURELAYERTYPE_LITTEXTURE:
10877 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10879 // two-pass lit texture with 2x rgbscale
10880 // first the lightmap pass
10881 R_Mesh_TexBind(0, r_texture_white);
10882 R_Mesh_TexMatrix(0, NULL);
10883 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10884 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10885 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10886 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10887 else if (rsurface.uselightmaptexture)
10888 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10890 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10891 // then apply the texture to it
10892 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10893 R_Mesh_TexBind(0, layer->texture);
10894 R_Mesh_TexMatrix(0, &layer->texmatrix);
10895 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10896 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10897 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);
10901 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10902 R_Mesh_TexBind(0, layer->texture);
10903 R_Mesh_TexMatrix(0, &layer->texmatrix);
10904 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10905 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10906 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10907 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);
10909 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);
10912 case TEXTURELAYERTYPE_TEXTURE:
10913 // singletexture unlit texture with transparency support
10914 R_Mesh_TexBind(0, layer->texture);
10915 R_Mesh_TexMatrix(0, &layer->texmatrix);
10916 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10917 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10918 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);
10920 case TEXTURELAYERTYPE_FOG:
10921 // singletexture fogging
10922 if (layer->texture)
10924 R_Mesh_TexBind(0, layer->texture);
10925 R_Mesh_TexMatrix(0, &layer->texmatrix);
10926 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10927 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10931 R_Mesh_TexBind(0, 0);
10932 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10934 // generate a color array for the fog pass
10935 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10936 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10942 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10943 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)
10945 f = 1 - RSurf_FogVertex(v);
10946 c[0] = layer->color[0];
10947 c[1] = layer->color[1];
10948 c[2] = layer->color[2];
10949 c[3] = f * layer->color[3];
10952 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10955 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10959 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10961 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10962 GL_AlphaTest(false);
10966 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10970 GL_AlphaTest(false);
10971 R_Mesh_ColorPointer(NULL, 0, 0);
10972 R_Mesh_ResetTextureState();
10973 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10975 if(rsurface.texture && rsurface.texture->currentskinframe)
10977 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10978 c[3] *= rsurface.texture->currentalpha;
10988 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10990 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10991 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10992 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10995 // brighten it up (as texture value 127 means "unlit")
10996 c[0] *= 2 * r_refdef.view.colorscale;
10997 c[1] *= 2 * r_refdef.view.colorscale;
10998 c[2] *= 2 * r_refdef.view.colorscale;
11000 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11001 c[3] *= r_wateralpha.value;
11003 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11006 GL_DepthMask(false);
11008 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11010 GL_BlendFunc(GL_ONE, GL_ONE);
11011 GL_DepthMask(false);
11013 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11015 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11016 GL_DepthMask(false);
11018 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11020 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11021 GL_DepthMask(false);
11025 GL_BlendFunc(GL_ONE, GL_ZERO);
11026 GL_DepthMask(writedepth);
11029 rsurface.lightmapcolor4f = NULL;
11031 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11033 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11035 rsurface.lightmapcolor4f = NULL;
11036 rsurface.lightmapcolor4f_bufferobject = 0;
11037 rsurface.lightmapcolor4f_bufferoffset = 0;
11039 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11041 qboolean applycolor = true;
11044 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11046 r_refdef.lightmapintensity = 1;
11047 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11048 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11052 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11054 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11055 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11056 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11059 if(!rsurface.lightmapcolor4f)
11060 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11062 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11063 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11064 if(r_refdef.fogenabled)
11065 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11067 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11068 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11071 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11074 RSurf_SetupDepthAndCulling();
11075 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11077 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11080 switch (vid.renderpath)
11082 case RENDERPATH_GL20:
11083 case RENDERPATH_CGGL:
11084 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11086 case RENDERPATH_GL13:
11087 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11089 case RENDERPATH_GL11:
11090 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11096 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11099 RSurf_SetupDepthAndCulling();
11100 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11102 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11105 switch (vid.renderpath)
11107 case RENDERPATH_GL20:
11108 case RENDERPATH_CGGL:
11109 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11111 case RENDERPATH_GL13:
11112 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11114 case RENDERPATH_GL11:
11115 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11121 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11124 int texturenumsurfaces, endsurface;
11125 texture_t *texture;
11126 const msurface_t *surface;
11127 const msurface_t *texturesurfacelist[256];
11129 // if the model is static it doesn't matter what value we give for
11130 // wantnormals and wanttangents, so this logic uses only rules applicable
11131 // to a model, knowing that they are meaningless otherwise
11132 if (ent == r_refdef.scene.worldentity)
11133 RSurf_ActiveWorldEntity();
11134 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11135 RSurf_ActiveModelEntity(ent, false, false, false);
11138 switch (vid.renderpath)
11140 case RENDERPATH_GL20:
11141 case RENDERPATH_CGGL:
11142 RSurf_ActiveModelEntity(ent, true, true, false);
11144 case RENDERPATH_GL13:
11145 case RENDERPATH_GL11:
11146 RSurf_ActiveModelEntity(ent, true, false, false);
11151 if (r_transparentdepthmasking.integer)
11153 qboolean setup = false;
11154 for (i = 0;i < numsurfaces;i = j)
11157 surface = rsurface.modelsurfaces + surfacelist[i];
11158 texture = surface->texture;
11159 rsurface.texture = R_GetCurrentTexture(texture);
11160 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11161 // scan ahead until we find a different texture
11162 endsurface = min(i + 1024, numsurfaces);
11163 texturenumsurfaces = 0;
11164 texturesurfacelist[texturenumsurfaces++] = surface;
11165 for (;j < endsurface;j++)
11167 surface = rsurface.modelsurfaces + surfacelist[j];
11168 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11170 texturesurfacelist[texturenumsurfaces++] = surface;
11172 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11174 // render the range of surfaces as depth
11178 GL_ColorMask(0,0,0,0);
11180 GL_DepthTest(true);
11181 GL_BlendFunc(GL_ONE, GL_ZERO);
11182 GL_DepthMask(true);
11183 GL_AlphaTest(false);
11184 R_Mesh_ColorPointer(NULL, 0, 0);
11185 R_Mesh_ResetTextureState();
11186 R_SetupShader_DepthOrShadow();
11188 RSurf_SetupDepthAndCulling();
11189 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11190 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11193 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11196 for (i = 0;i < numsurfaces;i = j)
11199 surface = rsurface.modelsurfaces + surfacelist[i];
11200 texture = surface->texture;
11201 rsurface.texture = R_GetCurrentTexture(texture);
11202 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11203 // scan ahead until we find a different texture
11204 endsurface = min(i + 1024, numsurfaces);
11205 texturenumsurfaces = 0;
11206 texturesurfacelist[texturenumsurfaces++] = surface;
11207 for (;j < endsurface;j++)
11209 surface = rsurface.modelsurfaces + surfacelist[j];
11210 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11212 texturesurfacelist[texturenumsurfaces++] = surface;
11214 // render the range of surfaces
11215 if (ent == r_refdef.scene.worldentity)
11216 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11218 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11220 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11221 GL_AlphaTest(false);
11224 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11226 // transparent surfaces get pushed off into the transparent queue
11227 int surfacelistindex;
11228 const msurface_t *surface;
11229 vec3_t tempcenter, center;
11230 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11232 surface = texturesurfacelist[surfacelistindex];
11233 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11234 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11235 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11236 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11237 if (queueentity->transparent_offset) // transparent offset
11239 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11240 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11241 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11243 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11247 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11249 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11253 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11255 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11257 RSurf_SetupDepthAndCulling();
11258 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11259 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11263 if (!rsurface.texture->currentnumlayers)
11265 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11266 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11268 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11270 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11272 RSurf_SetupDepthAndCulling();
11273 GL_AlphaTest(false);
11274 R_Mesh_ColorPointer(NULL, 0, 0);
11275 R_Mesh_ResetTextureState();
11276 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11277 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11278 GL_DepthMask(true);
11279 GL_BlendFunc(GL_ONE, GL_ZERO);
11280 GL_Color(0, 0, 0, 1);
11281 GL_DepthTest(writedepth);
11282 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11284 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11286 RSurf_SetupDepthAndCulling();
11287 GL_AlphaTest(false);
11288 R_Mesh_ColorPointer(NULL, 0, 0);
11289 R_Mesh_ResetTextureState();
11290 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11291 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11292 GL_DepthMask(true);
11293 GL_BlendFunc(GL_ONE, GL_ZERO);
11294 GL_DepthTest(true);
11295 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11297 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11298 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11299 else if (!rsurface.texture->currentnumlayers)
11301 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11303 // in the deferred case, transparent surfaces were queued during prepass
11304 if (!r_shadow_usingdeferredprepass)
11305 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11309 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11310 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11315 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11318 texture_t *texture;
11319 // break the surface list down into batches by texture and use of lightmapping
11320 for (i = 0;i < numsurfaces;i = j)
11323 // texture is the base texture pointer, rsurface.texture is the
11324 // current frame/skin the texture is directing us to use (for example
11325 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11326 // use skin 1 instead)
11327 texture = surfacelist[i]->texture;
11328 rsurface.texture = R_GetCurrentTexture(texture);
11329 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11330 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11332 // if this texture is not the kind we want, skip ahead to the next one
11333 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11337 // simply scan ahead until we find a different texture or lightmap state
11338 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11340 // render the range of surfaces
11341 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11345 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11350 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11352 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11354 RSurf_SetupDepthAndCulling();
11355 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11356 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11360 if (!rsurface.texture->currentnumlayers)
11362 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11363 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11365 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11367 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11369 RSurf_SetupDepthAndCulling();
11370 GL_AlphaTest(false);
11371 R_Mesh_ColorPointer(NULL, 0, 0);
11372 R_Mesh_ResetTextureState();
11373 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11374 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11375 GL_DepthMask(true);
11376 GL_BlendFunc(GL_ONE, GL_ZERO);
11377 GL_Color(0, 0, 0, 1);
11378 GL_DepthTest(writedepth);
11379 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11381 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11383 RSurf_SetupDepthAndCulling();
11384 GL_AlphaTest(false);
11385 R_Mesh_ColorPointer(NULL, 0, 0);
11386 R_Mesh_ResetTextureState();
11387 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11388 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11389 GL_DepthMask(true);
11390 GL_BlendFunc(GL_ONE, GL_ZERO);
11391 GL_DepthTest(true);
11392 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11394 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11395 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11396 else if (!rsurface.texture->currentnumlayers)
11398 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11400 // in the deferred case, transparent surfaces were queued during prepass
11401 if (!r_shadow_usingdeferredprepass)
11402 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11406 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11407 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11412 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11415 texture_t *texture;
11416 // break the surface list down into batches by texture and use of lightmapping
11417 for (i = 0;i < numsurfaces;i = j)
11420 // texture is the base texture pointer, rsurface.texture is the
11421 // current frame/skin the texture is directing us to use (for example
11422 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11423 // use skin 1 instead)
11424 texture = surfacelist[i]->texture;
11425 rsurface.texture = R_GetCurrentTexture(texture);
11426 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11427 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11429 // if this texture is not the kind we want, skip ahead to the next one
11430 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11434 // simply scan ahead until we find a different texture or lightmap state
11435 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11437 // render the range of surfaces
11438 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11442 float locboxvertex3f[6*4*3] =
11444 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11445 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11446 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11447 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11448 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11449 1,0,0, 0,0,0, 0,1,0, 1,1,0
11452 unsigned short locboxelements[6*2*3] =
11457 12,13,14, 12,14,15,
11458 16,17,18, 16,18,19,
11462 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11465 cl_locnode_t *loc = (cl_locnode_t *)ent;
11467 float vertex3f[6*4*3];
11469 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11470 GL_DepthMask(false);
11471 GL_DepthRange(0, 1);
11472 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11473 GL_DepthTest(true);
11474 GL_CullFace(GL_NONE);
11475 R_EntityMatrix(&identitymatrix);
11477 R_Mesh_VertexPointer(vertex3f, 0, 0);
11478 R_Mesh_ColorPointer(NULL, 0, 0);
11479 R_Mesh_ResetTextureState();
11480 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11482 i = surfacelist[0];
11483 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11484 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11485 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11486 surfacelist[0] < 0 ? 0.5f : 0.125f);
11488 if (VectorCompare(loc->mins, loc->maxs))
11490 VectorSet(size, 2, 2, 2);
11491 VectorMA(loc->mins, -0.5f, size, mins);
11495 VectorCopy(loc->mins, mins);
11496 VectorSubtract(loc->maxs, loc->mins, size);
11499 for (i = 0;i < 6*4*3;)
11500 for (j = 0;j < 3;j++, i++)
11501 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11503 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11506 void R_DrawLocs(void)
11509 cl_locnode_t *loc, *nearestloc;
11511 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11512 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11514 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11515 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11519 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11521 if (decalsystem->decals)
11522 Mem_Free(decalsystem->decals);
11523 memset(decalsystem, 0, sizeof(*decalsystem));
11526 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)
11529 tridecal_t *decals;
11532 // expand or initialize the system
11533 if (decalsystem->maxdecals <= decalsystem->numdecals)
11535 decalsystem_t old = *decalsystem;
11536 qboolean useshortelements;
11537 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11538 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11539 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)));
11540 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11541 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11542 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11543 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11544 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11545 if (decalsystem->numdecals)
11546 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11548 Mem_Free(old.decals);
11549 for (i = 0;i < decalsystem->maxdecals*3;i++)
11550 decalsystem->element3i[i] = i;
11551 if (useshortelements)
11552 for (i = 0;i < decalsystem->maxdecals*3;i++)
11553 decalsystem->element3s[i] = i;
11556 // grab a decal and search for another free slot for the next one
11557 decals = decalsystem->decals;
11558 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11559 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11561 decalsystem->freedecal = i;
11562 if (decalsystem->numdecals <= i)
11563 decalsystem->numdecals = i + 1;
11565 // initialize the decal
11567 decal->triangleindex = triangleindex;
11568 decal->surfaceindex = surfaceindex;
11569 decal->decalsequence = decalsequence;
11570 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11571 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11572 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11573 decal->color4ub[0][3] = 255;
11574 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11575 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11576 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11577 decal->color4ub[1][3] = 255;
11578 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11579 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11580 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11581 decal->color4ub[2][3] = 255;
11582 decal->vertex3f[0][0] = v0[0];
11583 decal->vertex3f[0][1] = v0[1];
11584 decal->vertex3f[0][2] = v0[2];
11585 decal->vertex3f[1][0] = v1[0];
11586 decal->vertex3f[1][1] = v1[1];
11587 decal->vertex3f[1][2] = v1[2];
11588 decal->vertex3f[2][0] = v2[0];
11589 decal->vertex3f[2][1] = v2[1];
11590 decal->vertex3f[2][2] = v2[2];
11591 decal->texcoord2f[0][0] = t0[0];
11592 decal->texcoord2f[0][1] = t0[1];
11593 decal->texcoord2f[1][0] = t1[0];
11594 decal->texcoord2f[1][1] = t1[1];
11595 decal->texcoord2f[2][0] = t2[0];
11596 decal->texcoord2f[2][1] = t2[1];
11599 extern cvar_t cl_decals_bias;
11600 extern cvar_t cl_decals_models;
11601 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11602 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)
11604 matrix4x4_t projection;
11605 decalsystem_t *decalsystem;
11608 const float *vertex3f;
11609 const msurface_t *surface;
11610 const msurface_t *surfaces;
11611 const int *surfacelist;
11612 const texture_t *texture;
11614 int numsurfacelist;
11615 int surfacelistindex;
11622 float localorigin[3];
11623 float localnormal[3];
11624 float localmins[3];
11625 float localmaxs[3];
11631 float planes[6][4];
11633 float points[2][9][3];
11637 decalsystem = &ent->decalsystem;
11638 model = ent->model;
11639 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11641 R_DecalSystem_Reset(&ent->decalsystem);
11645 if (!model->brush.data_nodes && !cl_decals_models.integer)
11647 if (decalsystem->model)
11648 R_DecalSystem_Reset(decalsystem);
11652 if (decalsystem->model != model)
11653 R_DecalSystem_Reset(decalsystem);
11654 decalsystem->model = model;
11656 RSurf_ActiveModelEntity(ent, false, false, false);
11658 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11659 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11660 VectorNormalize(localnormal);
11661 localsize = worldsize*rsurface.inversematrixscale;
11662 localmins[0] = localorigin[0] - localsize;
11663 localmins[1] = localorigin[1] - localsize;
11664 localmins[2] = localorigin[2] - localsize;
11665 localmaxs[0] = localorigin[0] + localsize;
11666 localmaxs[1] = localorigin[1] + localsize;
11667 localmaxs[2] = localorigin[2] + localsize;
11669 //VectorCopy(localnormal, planes[4]);
11670 //VectorVectors(planes[4], planes[2], planes[0]);
11671 AnglesFromVectors(angles, localnormal, NULL, false);
11672 AngleVectors(angles, planes[0], planes[2], planes[4]);
11673 VectorNegate(planes[0], planes[1]);
11674 VectorNegate(planes[2], planes[3]);
11675 VectorNegate(planes[4], planes[5]);
11676 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11677 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11678 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11679 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11680 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11681 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11686 matrix4x4_t forwardprojection;
11687 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11688 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11693 float projectionvector[4][3];
11694 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11695 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11696 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11697 projectionvector[0][0] = planes[0][0] * ilocalsize;
11698 projectionvector[0][1] = planes[1][0] * ilocalsize;
11699 projectionvector[0][2] = planes[2][0] * ilocalsize;
11700 projectionvector[1][0] = planes[0][1] * ilocalsize;
11701 projectionvector[1][1] = planes[1][1] * ilocalsize;
11702 projectionvector[1][2] = planes[2][1] * ilocalsize;
11703 projectionvector[2][0] = planes[0][2] * ilocalsize;
11704 projectionvector[2][1] = planes[1][2] * ilocalsize;
11705 projectionvector[2][2] = planes[2][2] * ilocalsize;
11706 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11707 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11708 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11709 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11713 dynamic = model->surfmesh.isanimated;
11714 vertex3f = rsurface.modelvertex3f;
11715 numsurfacelist = model->nummodelsurfaces;
11716 surfacelist = model->sortedmodelsurfaces;
11717 surfaces = model->data_surfaces;
11718 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11720 surfaceindex = surfacelist[surfacelistindex];
11721 surface = surfaces + surfaceindex;
11722 // check cull box first because it rejects more than any other check
11723 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11725 // skip transparent surfaces
11726 texture = surface->texture;
11727 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11729 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11731 numtriangles = surface->num_triangles;
11732 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11734 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11736 index = 3*e[cornerindex];
11737 VectorCopy(vertex3f + index, v[cornerindex]);
11740 //TriangleNormal(v[0], v[1], v[2], normal);
11741 //if (DotProduct(normal, localnormal) < 0.0f)
11743 // clip by each of the box planes formed from the projection matrix
11744 // if anything survives, we emit the decal
11745 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]);
11748 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]);
11751 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]);
11754 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]);
11757 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]);
11760 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]);
11763 // some part of the triangle survived, so we have to accept it...
11766 // dynamic always uses the original triangle
11768 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11770 index = 3*e[cornerindex];
11771 VectorCopy(vertex3f + index, v[cornerindex]);
11774 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11776 // convert vertex positions to texcoords
11777 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11778 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11779 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11780 // calculate distance fade from the projection origin
11781 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11782 f = bound(0.0f, f, 1.0f);
11783 c[cornerindex][0] = r * f;
11784 c[cornerindex][1] = g * f;
11785 c[cornerindex][2] = b * f;
11786 c[cornerindex][3] = 1.0f;
11787 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11790 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);
11792 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11793 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);
11798 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11799 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)
11801 int renderentityindex;
11802 float worldmins[3];
11803 float worldmaxs[3];
11804 entity_render_t *ent;
11806 if (!cl_decals_newsystem.integer)
11809 worldmins[0] = worldorigin[0] - worldsize;
11810 worldmins[1] = worldorigin[1] - worldsize;
11811 worldmins[2] = worldorigin[2] - worldsize;
11812 worldmaxs[0] = worldorigin[0] + worldsize;
11813 worldmaxs[1] = worldorigin[1] + worldsize;
11814 worldmaxs[2] = worldorigin[2] + worldsize;
11816 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11818 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11820 ent = r_refdef.scene.entities[renderentityindex];
11821 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11824 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11828 typedef struct r_decalsystem_splatqueue_s
11830 vec3_t worldorigin;
11831 vec3_t worldnormal;
11837 r_decalsystem_splatqueue_t;
11839 int r_decalsystem_numqueued = 0;
11840 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11842 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)
11844 r_decalsystem_splatqueue_t *queue;
11846 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11849 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11850 VectorCopy(worldorigin, queue->worldorigin);
11851 VectorCopy(worldnormal, queue->worldnormal);
11852 Vector4Set(queue->color, r, g, b, a);
11853 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11854 queue->worldsize = worldsize;
11855 queue->decalsequence = cl.decalsequence++;
11858 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11861 r_decalsystem_splatqueue_t *queue;
11863 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11864 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);
11865 r_decalsystem_numqueued = 0;
11868 extern cvar_t cl_decals_max;
11869 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11872 decalsystem_t *decalsystem = &ent->decalsystem;
11879 if (!decalsystem->numdecals)
11882 if (r_showsurfaces.integer)
11885 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11887 R_DecalSystem_Reset(decalsystem);
11891 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11892 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11894 if (decalsystem->lastupdatetime)
11895 frametime = (cl.time - decalsystem->lastupdatetime);
11898 decalsystem->lastupdatetime = cl.time;
11899 decal = decalsystem->decals;
11900 numdecals = decalsystem->numdecals;
11902 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11904 if (decal->color4ub[0][3])
11906 decal->lived += frametime;
11907 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11909 memset(decal, 0, sizeof(*decal));
11910 if (decalsystem->freedecal > i)
11911 decalsystem->freedecal = i;
11915 decal = decalsystem->decals;
11916 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11919 // collapse the array by shuffling the tail decals into the gaps
11922 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11923 decalsystem->freedecal++;
11924 if (decalsystem->freedecal == numdecals)
11926 decal[decalsystem->freedecal] = decal[--numdecals];
11929 decalsystem->numdecals = numdecals;
11931 if (numdecals <= 0)
11933 // if there are no decals left, reset decalsystem
11934 R_DecalSystem_Reset(decalsystem);
11938 extern skinframe_t *decalskinframe;
11939 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11942 decalsystem_t *decalsystem = &ent->decalsystem;
11951 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11954 numdecals = decalsystem->numdecals;
11958 if (r_showsurfaces.integer)
11961 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11963 R_DecalSystem_Reset(decalsystem);
11967 // if the model is static it doesn't matter what value we give for
11968 // wantnormals and wanttangents, so this logic uses only rules applicable
11969 // to a model, knowing that they are meaningless otherwise
11970 if (ent == r_refdef.scene.worldentity)
11971 RSurf_ActiveWorldEntity();
11973 RSurf_ActiveModelEntity(ent, false, false, false);
11975 decalsystem->lastupdatetime = cl.time;
11976 decal = decalsystem->decals;
11978 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11980 // update vertex positions for animated models
11981 v3f = decalsystem->vertex3f;
11982 c4f = decalsystem->color4f;
11983 t2f = decalsystem->texcoord2f;
11984 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11986 if (!decal->color4ub[0][3])
11989 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11992 // update color values for fading decals
11993 if (decal->lived >= cl_decals_time.value)
11995 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11996 alpha *= (1.0f/255.0f);
11999 alpha = 1.0f/255.0f;
12001 c4f[ 0] = decal->color4ub[0][0] * alpha;
12002 c4f[ 1] = decal->color4ub[0][1] * alpha;
12003 c4f[ 2] = decal->color4ub[0][2] * alpha;
12005 c4f[ 4] = decal->color4ub[1][0] * alpha;
12006 c4f[ 5] = decal->color4ub[1][1] * alpha;
12007 c4f[ 6] = decal->color4ub[1][2] * alpha;
12009 c4f[ 8] = decal->color4ub[2][0] * alpha;
12010 c4f[ 9] = decal->color4ub[2][1] * alpha;
12011 c4f[10] = decal->color4ub[2][2] * alpha;
12014 t2f[0] = decal->texcoord2f[0][0];
12015 t2f[1] = decal->texcoord2f[0][1];
12016 t2f[2] = decal->texcoord2f[1][0];
12017 t2f[3] = decal->texcoord2f[1][1];
12018 t2f[4] = decal->texcoord2f[2][0];
12019 t2f[5] = decal->texcoord2f[2][1];
12021 // update vertex positions for animated models
12022 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12024 e = rsurface.modelelement3i + 3*decal->triangleindex;
12025 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12026 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12027 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12031 VectorCopy(decal->vertex3f[0], v3f);
12032 VectorCopy(decal->vertex3f[1], v3f + 3);
12033 VectorCopy(decal->vertex3f[2], v3f + 6);
12036 if (r_refdef.fogenabled)
12038 alpha = RSurf_FogVertex(v3f);
12039 VectorScale(c4f, alpha, c4f);
12040 alpha = RSurf_FogVertex(v3f + 3);
12041 VectorScale(c4f + 4, alpha, c4f + 4);
12042 alpha = RSurf_FogVertex(v3f + 6);
12043 VectorScale(c4f + 8, alpha, c4f + 8);
12054 r_refdef.stats.drawndecals += numtris;
12056 // now render the decals all at once
12057 // (this assumes they all use one particle font texture!)
12058 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);
12059 R_Mesh_ResetTextureState();
12060 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12061 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12062 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12063 GL_DepthMask(false);
12064 GL_DepthRange(0, 1);
12065 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12066 GL_DepthTest(true);
12067 GL_CullFace(GL_NONE);
12068 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12069 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12070 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12074 static void R_DrawModelDecals(void)
12078 // fade faster when there are too many decals
12079 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12080 for (i = 0;i < r_refdef.scene.numentities;i++)
12081 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12083 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12084 for (i = 0;i < r_refdef.scene.numentities;i++)
12085 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12086 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12088 R_DecalSystem_ApplySplatEntitiesQueue();
12090 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12091 for (i = 0;i < r_refdef.scene.numentities;i++)
12092 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12094 r_refdef.stats.totaldecals += numdecals;
12096 if (r_showsurfaces.integer)
12099 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12101 for (i = 0;i < r_refdef.scene.numentities;i++)
12103 if (!r_refdef.viewcache.entityvisible[i])
12105 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12106 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12110 void R_DrawDebugModel(void)
12112 entity_render_t *ent = rsurface.entity;
12113 int i, j, k, l, flagsmask;
12115 const msurface_t *surface;
12116 dp_model_t *model = ent->model;
12119 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12121 R_Mesh_ColorPointer(NULL, 0, 0);
12122 R_Mesh_ResetTextureState();
12123 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12124 GL_DepthRange(0, 1);
12125 GL_DepthTest(!r_showdisabledepthtest.integer);
12126 GL_DepthMask(false);
12127 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12129 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12131 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12132 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12134 if (brush->colbrushf && brush->colbrushf->numtriangles)
12136 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12137 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12138 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12141 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12143 if (surface->num_collisiontriangles)
12145 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12146 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12147 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12152 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12154 if (r_showtris.integer || r_shownormals.integer)
12156 if (r_showdisabledepthtest.integer)
12158 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12159 GL_DepthMask(false);
12163 GL_BlendFunc(GL_ONE, GL_ZERO);
12164 GL_DepthMask(true);
12166 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12168 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12170 rsurface.texture = R_GetCurrentTexture(surface->texture);
12171 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12173 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12174 if (r_showtris.value > 0)
12176 if (!rsurface.texture->currentlayers->depthmask)
12177 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12178 else if (ent == r_refdef.scene.worldentity)
12179 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12181 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12182 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12183 R_Mesh_ColorPointer(NULL, 0, 0);
12184 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12185 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12186 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12187 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);
12188 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12191 if (r_shownormals.value < 0)
12193 qglBegin(GL_LINES);
12194 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12196 VectorCopy(rsurface.vertex3f + l * 3, v);
12197 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12198 qglVertex3f(v[0], v[1], v[2]);
12199 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12200 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12201 qglVertex3f(v[0], v[1], v[2]);
12206 if (r_shownormals.value > 0)
12208 qglBegin(GL_LINES);
12209 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12211 VectorCopy(rsurface.vertex3f + l * 3, v);
12212 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12213 qglVertex3f(v[0], v[1], v[2]);
12214 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12215 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12216 qglVertex3f(v[0], v[1], v[2]);
12220 qglBegin(GL_LINES);
12221 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12223 VectorCopy(rsurface.vertex3f + l * 3, v);
12224 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12225 qglVertex3f(v[0], v[1], v[2]);
12226 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12227 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12228 qglVertex3f(v[0], v[1], v[2]);
12232 qglBegin(GL_LINES);
12233 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12235 VectorCopy(rsurface.vertex3f + l * 3, v);
12236 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12237 qglVertex3f(v[0], v[1], v[2]);
12238 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12239 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12240 qglVertex3f(v[0], v[1], v[2]);
12247 rsurface.texture = NULL;
12251 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12252 int r_maxsurfacelist = 0;
12253 const msurface_t **r_surfacelist = NULL;
12254 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12256 int i, j, endj, flagsmask;
12257 dp_model_t *model = r_refdef.scene.worldmodel;
12258 msurface_t *surfaces;
12259 unsigned char *update;
12260 int numsurfacelist = 0;
12264 if (r_maxsurfacelist < model->num_surfaces)
12266 r_maxsurfacelist = model->num_surfaces;
12268 Mem_Free((msurface_t**)r_surfacelist);
12269 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12272 RSurf_ActiveWorldEntity();
12274 surfaces = model->data_surfaces;
12275 update = model->brushq1.lightmapupdateflags;
12277 // update light styles on this submodel
12278 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12280 model_brush_lightstyleinfo_t *style;
12281 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12283 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12285 int *list = style->surfacelist;
12286 style->value = r_refdef.scene.lightstylevalue[style->style];
12287 for (j = 0;j < style->numsurfaces;j++)
12288 update[list[j]] = true;
12293 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12297 R_DrawDebugModel();
12298 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12302 rsurface.uselightmaptexture = false;
12303 rsurface.texture = NULL;
12304 rsurface.rtlight = NULL;
12305 numsurfacelist = 0;
12306 // add visible surfaces to draw list
12307 for (i = 0;i < model->nummodelsurfaces;i++)
12309 j = model->sortedmodelsurfaces[i];
12310 if (r_refdef.viewcache.world_surfacevisible[j])
12311 r_surfacelist[numsurfacelist++] = surfaces + j;
12313 // update lightmaps if needed
12314 if (model->brushq1.firstrender)
12316 model->brushq1.firstrender = false;
12317 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12319 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12323 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12324 if (r_refdef.viewcache.world_surfacevisible[j])
12326 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12328 // don't do anything if there were no surfaces
12329 if (!numsurfacelist)
12331 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12334 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12335 GL_AlphaTest(false);
12337 // add to stats if desired
12338 if (r_speeds.integer && !skysurfaces && !depthonly)
12340 r_refdef.stats.world_surfaces += numsurfacelist;
12341 for (j = 0;j < numsurfacelist;j++)
12342 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12345 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12348 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12350 int i, j, endj, flagsmask;
12351 dp_model_t *model = ent->model;
12352 msurface_t *surfaces;
12353 unsigned char *update;
12354 int numsurfacelist = 0;
12358 if (r_maxsurfacelist < model->num_surfaces)
12360 r_maxsurfacelist = model->num_surfaces;
12362 Mem_Free((msurface_t **)r_surfacelist);
12363 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12366 // if the model is static it doesn't matter what value we give for
12367 // wantnormals and wanttangents, so this logic uses only rules applicable
12368 // to a model, knowing that they are meaningless otherwise
12369 if (ent == r_refdef.scene.worldentity)
12370 RSurf_ActiveWorldEntity();
12371 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12372 RSurf_ActiveModelEntity(ent, false, false, false);
12374 RSurf_ActiveModelEntity(ent, true, true, true);
12375 else if (depthonly)
12377 switch (vid.renderpath)
12379 case RENDERPATH_GL20:
12380 case RENDERPATH_CGGL:
12381 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12383 case RENDERPATH_GL13:
12384 case RENDERPATH_GL11:
12385 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12391 switch (vid.renderpath)
12393 case RENDERPATH_GL20:
12394 case RENDERPATH_CGGL:
12395 RSurf_ActiveModelEntity(ent, true, true, false);
12397 case RENDERPATH_GL13:
12398 case RENDERPATH_GL11:
12399 RSurf_ActiveModelEntity(ent, true, false, false);
12404 surfaces = model->data_surfaces;
12405 update = model->brushq1.lightmapupdateflags;
12407 // update light styles
12408 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12410 model_brush_lightstyleinfo_t *style;
12411 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12413 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12415 int *list = style->surfacelist;
12416 style->value = r_refdef.scene.lightstylevalue[style->style];
12417 for (j = 0;j < style->numsurfaces;j++)
12418 update[list[j]] = true;
12423 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12427 R_DrawDebugModel();
12428 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12432 rsurface.uselightmaptexture = false;
12433 rsurface.texture = NULL;
12434 rsurface.rtlight = NULL;
12435 numsurfacelist = 0;
12436 // add visible surfaces to draw list
12437 for (i = 0;i < model->nummodelsurfaces;i++)
12438 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12439 // don't do anything if there were no surfaces
12440 if (!numsurfacelist)
12442 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12445 // update lightmaps if needed
12449 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12454 R_BuildLightMap(ent, surfaces + j);
12459 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12461 R_BuildLightMap(ent, surfaces + j);
12462 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12463 GL_AlphaTest(false);
12465 // add to stats if desired
12466 if (r_speeds.integer && !skysurfaces && !depthonly)
12468 r_refdef.stats.entities_surfaces += numsurfacelist;
12469 for (j = 0;j < numsurfacelist;j++)
12470 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12473 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12476 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12478 static texture_t texture;
12479 static msurface_t surface;
12480 const msurface_t *surfacelist = &surface;
12482 // fake enough texture and surface state to render this geometry
12484 texture.update_lastrenderframe = -1; // regenerate this texture
12485 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12486 texture.currentskinframe = skinframe;
12487 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12488 texture.specularscalemod = 1;
12489 texture.specularpowermod = 1;
12491 surface.texture = &texture;
12492 surface.num_triangles = numtriangles;
12493 surface.num_firsttriangle = firsttriangle;
12494 surface.num_vertices = numvertices;
12495 surface.num_firstvertex = firstvertex;
12498 rsurface.texture = R_GetCurrentTexture(surface.texture);
12499 rsurface.uselightmaptexture = false;
12500 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12503 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)
12505 static msurface_t surface;
12506 const msurface_t *surfacelist = &surface;
12508 // fake enough texture and surface state to render this geometry
12510 surface.texture = texture;
12511 surface.num_triangles = numtriangles;
12512 surface.num_firsttriangle = firsttriangle;
12513 surface.num_vertices = numvertices;
12514 surface.num_firstvertex = firstvertex;
12517 rsurface.texture = R_GetCurrentTexture(surface.texture);
12518 rsurface.uselightmaptexture = false;
12519 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);