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) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6794 if (!r_drawviewmodel.integer)
6795 renderimask |= RENDER_VIEWMODEL;
6796 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6798 // worldmodel can check visibility
6799 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6800 for (i = 0;i < r_refdef.scene.numentities;i++)
6802 ent = r_refdef.scene.entities[i];
6803 if (!(ent->flags & renderimask))
6804 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)))
6805 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))
6806 r_refdef.viewcache.entityvisible[i] = true;
6808 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6810 for (i = 0;i < r_refdef.scene.numentities;i++)
6812 ent = r_refdef.scene.entities[i];
6813 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6815 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6817 continue; // temp entities do pvs only
6818 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6819 ent->last_trace_visibility = realtime;
6820 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6821 r_refdef.viewcache.entityvisible[i] = 0;
6828 // no worldmodel or it can't check visibility
6829 for (i = 0;i < r_refdef.scene.numentities;i++)
6831 ent = r_refdef.scene.entities[i];
6832 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));
6837 /// only used if skyrendermasked, and normally returns false
6838 int R_DrawBrushModelsSky (void)
6841 entity_render_t *ent;
6844 for (i = 0;i < r_refdef.scene.numentities;i++)
6846 if (!r_refdef.viewcache.entityvisible[i])
6848 ent = r_refdef.scene.entities[i];
6849 if (!ent->model || !ent->model->DrawSky)
6851 ent->model->DrawSky(ent);
6857 static void R_DrawNoModel(entity_render_t *ent);
6858 static void R_DrawModels(void)
6861 entity_render_t *ent;
6863 for (i = 0;i < r_refdef.scene.numentities;i++)
6865 if (!r_refdef.viewcache.entityvisible[i])
6867 ent = r_refdef.scene.entities[i];
6868 r_refdef.stats.entities++;
6869 if (ent->model && ent->model->Draw != NULL)
6870 ent->model->Draw(ent);
6876 static void R_DrawModelsDepth(void)
6879 entity_render_t *ent;
6881 for (i = 0;i < r_refdef.scene.numentities;i++)
6883 if (!r_refdef.viewcache.entityvisible[i])
6885 ent = r_refdef.scene.entities[i];
6886 if (ent->model && ent->model->DrawDepth != NULL)
6887 ent->model->DrawDepth(ent);
6891 static void R_DrawModelsDebug(void)
6894 entity_render_t *ent;
6896 for (i = 0;i < r_refdef.scene.numentities;i++)
6898 if (!r_refdef.viewcache.entityvisible[i])
6900 ent = r_refdef.scene.entities[i];
6901 if (ent->model && ent->model->DrawDebug != NULL)
6902 ent->model->DrawDebug(ent);
6906 static void R_DrawModelsAddWaterPlanes(void)
6909 entity_render_t *ent;
6911 for (i = 0;i < r_refdef.scene.numentities;i++)
6913 if (!r_refdef.viewcache.entityvisible[i])
6915 ent = r_refdef.scene.entities[i];
6916 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6917 ent->model->DrawAddWaterPlanes(ent);
6921 static void R_View_SetFrustum(void)
6924 double slopex, slopey;
6925 vec3_t forward, left, up, origin;
6927 // we can't trust r_refdef.view.forward and friends in reflected scenes
6928 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6931 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6932 r_refdef.view.frustum[0].normal[1] = 0 - 0;
6933 r_refdef.view.frustum[0].normal[2] = -1 - 0;
6934 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6935 r_refdef.view.frustum[1].normal[1] = 0 + 0;
6936 r_refdef.view.frustum[1].normal[2] = -1 + 0;
6937 r_refdef.view.frustum[2].normal[0] = 0 - 0;
6938 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6939 r_refdef.view.frustum[2].normal[2] = -1 - 0;
6940 r_refdef.view.frustum[3].normal[0] = 0 + 0;
6941 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6942 r_refdef.view.frustum[3].normal[2] = -1 + 0;
6946 zNear = r_refdef.nearclip;
6947 nudge = 1.0 - 1.0 / (1<<23);
6948 r_refdef.view.frustum[4].normal[0] = 0 - 0;
6949 r_refdef.view.frustum[4].normal[1] = 0 - 0;
6950 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6951 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6952 r_refdef.view.frustum[5].normal[0] = 0 + 0;
6953 r_refdef.view.frustum[5].normal[1] = 0 + 0;
6954 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6955 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6961 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6962 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6963 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6964 r_refdef.view.frustum[0].dist = m[15] - m[12];
6966 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6967 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6968 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6969 r_refdef.view.frustum[1].dist = m[15] + m[12];
6971 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6972 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6973 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6974 r_refdef.view.frustum[2].dist = m[15] - m[13];
6976 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6977 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6978 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6979 r_refdef.view.frustum[3].dist = m[15] + m[13];
6981 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6982 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6983 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6984 r_refdef.view.frustum[4].dist = m[15] - m[14];
6986 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6987 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6988 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6989 r_refdef.view.frustum[5].dist = m[15] + m[14];
6992 if (r_refdef.view.useperspective)
6994 slopex = 1.0 / r_refdef.view.frustum_x;
6995 slopey = 1.0 / r_refdef.view.frustum_y;
6996 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6997 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
6998 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
6999 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7000 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7002 // Leaving those out was a mistake, those were in the old code, and they
7003 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7004 // I couldn't reproduce it after adding those normalizations. --blub
7005 VectorNormalize(r_refdef.view.frustum[0].normal);
7006 VectorNormalize(r_refdef.view.frustum[1].normal);
7007 VectorNormalize(r_refdef.view.frustum[2].normal);
7008 VectorNormalize(r_refdef.view.frustum[3].normal);
7010 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7011 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]);
7012 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]);
7013 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]);
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[3]);
7016 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7017 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7018 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7019 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7020 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7024 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7025 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7026 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7027 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7028 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7029 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7030 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7031 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7032 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7033 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7035 r_refdef.view.numfrustumplanes = 5;
7037 if (r_refdef.view.useclipplane)
7039 r_refdef.view.numfrustumplanes = 6;
7040 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7043 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7044 PlaneClassify(r_refdef.view.frustum + i);
7046 // LordHavoc: note to all quake engine coders, Quake had a special case
7047 // for 90 degrees which assumed a square view (wrong), so I removed it,
7048 // Quake2 has it disabled as well.
7050 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7051 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7052 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7053 //PlaneClassify(&frustum[0]);
7055 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7056 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7057 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7058 //PlaneClassify(&frustum[1]);
7060 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7061 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7062 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7063 //PlaneClassify(&frustum[2]);
7065 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7066 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7067 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7068 //PlaneClassify(&frustum[3]);
7071 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7072 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7073 //PlaneClassify(&frustum[4]);
7076 void R_View_Update(void)
7078 R_Main_ResizeViewCache();
7079 R_View_SetFrustum();
7080 R_View_WorldVisibility(r_refdef.view.useclipplane);
7081 R_View_UpdateEntityVisible();
7082 R_View_UpdateEntityLighting();
7085 void R_SetupView(qboolean allowwaterclippingplane)
7087 const float *customclipplane = NULL;
7089 if (r_refdef.view.useclipplane && allowwaterclippingplane)
7091 // LordHavoc: couldn't figure out how to make this approach the
7092 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7093 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7094 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7095 dist = r_refdef.view.clipplane.dist;
7096 plane[0] = r_refdef.view.clipplane.normal[0];
7097 plane[1] = r_refdef.view.clipplane.normal[1];
7098 plane[2] = r_refdef.view.clipplane.normal[2];
7100 customclipplane = plane;
7103 if (!r_refdef.view.useperspective)
7104 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);
7105 else if (vid.stencil && r_useinfinitefarclip.integer)
7106 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);
7108 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);
7109 R_SetViewport(&r_refdef.view.viewport);
7112 void R_EntityMatrix(const matrix4x4_t *matrix)
7114 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7116 gl_modelmatrixchanged = false;
7117 gl_modelmatrix = *matrix;
7118 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7119 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7120 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7121 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7123 switch(vid.renderpath)
7125 case RENDERPATH_GL20:
7126 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7127 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7128 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7130 case RENDERPATH_CGGL:
7133 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7134 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7135 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7138 case RENDERPATH_GL13:
7139 case RENDERPATH_GL11:
7140 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7146 void R_ResetViewRendering2D(void)
7148 r_viewport_t viewport;
7151 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7152 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);
7153 R_SetViewport(&viewport);
7154 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7155 GL_Color(1, 1, 1, 1);
7156 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7157 GL_BlendFunc(GL_ONE, GL_ZERO);
7158 GL_AlphaTest(false);
7159 GL_ScissorTest(false);
7160 GL_DepthMask(false);
7161 GL_DepthRange(0, 1);
7162 GL_DepthTest(false);
7163 R_EntityMatrix(&identitymatrix);
7164 R_Mesh_ResetTextureState();
7165 GL_PolygonOffset(0, 0);
7166 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7167 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7168 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7169 qglStencilMask(~0);CHECKGLERROR
7170 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7171 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7172 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7175 void R_ResetViewRendering3D(void)
7180 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7181 GL_Color(1, 1, 1, 1);
7182 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7183 GL_BlendFunc(GL_ONE, GL_ZERO);
7184 GL_AlphaTest(false);
7185 GL_ScissorTest(true);
7187 GL_DepthRange(0, 1);
7189 R_EntityMatrix(&identitymatrix);
7190 R_Mesh_ResetTextureState();
7191 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7192 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7193 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7194 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7195 qglStencilMask(~0);CHECKGLERROR
7196 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7197 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7198 GL_CullFace(r_refdef.view.cullface_back);
7201 void R_RenderScene(void);
7202 void R_RenderWaterPlanes(void);
7204 static void R_Water_StartFrame(void)
7207 int waterwidth, waterheight, texturewidth, textureheight;
7208 r_waterstate_waterplane_t *p;
7210 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7213 switch(vid.renderpath)
7215 case RENDERPATH_GL20:
7216 case RENDERPATH_CGGL:
7218 case RENDERPATH_GL13:
7219 case RENDERPATH_GL11:
7223 // set waterwidth and waterheight to the water resolution that will be
7224 // used (often less than the screen resolution for faster rendering)
7225 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7226 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7228 // calculate desired texture sizes
7229 // can't use water if the card does not support the texture size
7230 if (!r_water.integer || r_showsurfaces.integer)
7231 texturewidth = textureheight = waterwidth = waterheight = 0;
7232 else if (vid.support.arb_texture_non_power_of_two)
7234 texturewidth = waterwidth;
7235 textureheight = waterheight;
7239 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
7240 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
7243 // allocate textures as needed
7244 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7246 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7247 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7249 if (p->texture_refraction)
7250 R_FreeTexture(p->texture_refraction);
7251 p->texture_refraction = NULL;
7252 if (p->texture_reflection)
7253 R_FreeTexture(p->texture_reflection);
7254 p->texture_reflection = NULL;
7256 memset(&r_waterstate, 0, sizeof(r_waterstate));
7257 r_waterstate.texturewidth = texturewidth;
7258 r_waterstate.textureheight = textureheight;
7261 if (r_waterstate.texturewidth)
7263 r_waterstate.enabled = true;
7265 // when doing a reduced render (HDR) we want to use a smaller area
7266 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7267 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7269 // set up variables that will be used in shader setup
7270 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7271 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7272 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7273 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7276 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7277 r_waterstate.numwaterplanes = 0;
7280 void R_Water_AddWaterPlane(msurface_t *surface)
7282 int triangleindex, planeindex;
7288 r_waterstate_waterplane_t *p;
7289 texture_t *t = R_GetCurrentTexture(surface->texture);
7290 // just use the first triangle with a valid normal for any decisions
7291 VectorClear(normal);
7292 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7294 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7295 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7296 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7297 TriangleNormal(vert[0], vert[1], vert[2], normal);
7298 if (VectorLength2(normal) >= 0.001)
7302 VectorCopy(normal, plane.normal);
7303 VectorNormalize(plane.normal);
7304 plane.dist = DotProduct(vert[0], plane.normal);
7305 PlaneClassify(&plane);
7306 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7308 // skip backfaces (except if nocullface is set)
7309 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7311 VectorNegate(plane.normal, plane.normal);
7313 PlaneClassify(&plane);
7317 // find a matching plane if there is one
7318 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7319 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7321 if (planeindex >= r_waterstate.maxwaterplanes)
7322 return; // nothing we can do, out of planes
7324 // if this triangle does not fit any known plane rendered this frame, add one
7325 if (planeindex >= r_waterstate.numwaterplanes)
7327 // store the new plane
7328 r_waterstate.numwaterplanes++;
7330 // clear materialflags and pvs
7331 p->materialflags = 0;
7332 p->pvsvalid = false;
7334 // merge this surface's materialflags into the waterplane
7335 p->materialflags |= t->currentmaterialflags;
7336 // merge this surface's PVS into the waterplane
7337 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7338 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7339 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7341 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7346 static void R_Water_ProcessPlanes(void)
7348 r_refdef_view_t originalview;
7349 r_refdef_view_t myview;
7351 r_waterstate_waterplane_t *p;
7353 originalview = r_refdef.view;
7355 // make sure enough textures are allocated
7356 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7358 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7360 if (!p->texture_refraction)
7361 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);
7362 if (!p->texture_refraction)
7366 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7368 if (!p->texture_reflection)
7369 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);
7370 if (!p->texture_reflection)
7376 r_refdef.view = originalview;
7377 r_refdef.view.showdebug = false;
7378 r_refdef.view.width = r_waterstate.waterwidth;
7379 r_refdef.view.height = r_waterstate.waterheight;
7380 r_refdef.view.useclipplane = true;
7381 myview = r_refdef.view;
7382 r_waterstate.renderingscene = true;
7383 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7385 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7387 r_refdef.view = myview;
7388 // render reflected scene and copy into texture
7389 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7390 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7391 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7392 r_refdef.view.clipplane = p->plane;
7393 // reverse the cullface settings for this render
7394 r_refdef.view.cullface_front = GL_FRONT;
7395 r_refdef.view.cullface_back = GL_BACK;
7396 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7398 r_refdef.view.usecustompvs = true;
7400 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7402 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7405 R_ResetViewRendering3D();
7406 R_ClearScreen(r_refdef.fogenabled);
7410 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);
7413 // render the normal view scene and copy into texture
7414 // (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)
7415 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7417 r_refdef.view = myview;
7418 r_refdef.view.clipplane = p->plane;
7419 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7420 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7421 PlaneClassify(&r_refdef.view.clipplane);
7423 R_ResetViewRendering3D();
7424 R_ClearScreen(r_refdef.fogenabled);
7428 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);
7432 r_waterstate.renderingscene = false;
7433 r_refdef.view = originalview;
7434 R_ResetViewRendering3D();
7435 R_ClearScreen(r_refdef.fogenabled);
7439 r_refdef.view = originalview;
7440 r_waterstate.renderingscene = false;
7441 Cvar_SetValueQuick(&r_water, 0);
7442 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
7446 void R_Bloom_StartFrame(void)
7448 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7450 switch(vid.renderpath)
7452 case RENDERPATH_GL20:
7453 case RENDERPATH_CGGL:
7455 case RENDERPATH_GL13:
7456 case RENDERPATH_GL11:
7460 // set bloomwidth and bloomheight to the bloom resolution that will be
7461 // used (often less than the screen resolution for faster rendering)
7462 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7463 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7464 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7465 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7466 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7468 // calculate desired texture sizes
7469 if (vid.support.arb_texture_non_power_of_two)
7471 screentexturewidth = r_refdef.view.width;
7472 screentextureheight = r_refdef.view.height;
7473 bloomtexturewidth = r_bloomstate.bloomwidth;
7474 bloomtextureheight = r_bloomstate.bloomheight;
7478 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
7479 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
7480 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
7481 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
7484 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))
7486 Cvar_SetValueQuick(&r_hdr, 0);
7487 Cvar_SetValueQuick(&r_bloom, 0);
7488 Cvar_SetValueQuick(&r_motionblur, 0);
7489 Cvar_SetValueQuick(&r_damageblur, 0);
7492 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)))
7493 screentexturewidth = screentextureheight = 0;
7494 if (!r_hdr.integer && !r_bloom.integer)
7495 bloomtexturewidth = bloomtextureheight = 0;
7497 // allocate textures as needed
7498 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7500 if (r_bloomstate.texture_screen)
7501 R_FreeTexture(r_bloomstate.texture_screen);
7502 r_bloomstate.texture_screen = NULL;
7503 r_bloomstate.screentexturewidth = screentexturewidth;
7504 r_bloomstate.screentextureheight = screentextureheight;
7505 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7506 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7508 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7510 if (r_bloomstate.texture_bloom)
7511 R_FreeTexture(r_bloomstate.texture_bloom);
7512 r_bloomstate.texture_bloom = NULL;
7513 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7514 r_bloomstate.bloomtextureheight = bloomtextureheight;
7515 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7516 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7519 // when doing a reduced render (HDR) we want to use a smaller area
7520 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7521 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7522 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7523 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7524 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7526 // set up a texcoord array for the full resolution screen image
7527 // (we have to keep this around to copy back during final render)
7528 r_bloomstate.screentexcoord2f[0] = 0;
7529 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7530 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7531 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
7532 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
7533 r_bloomstate.screentexcoord2f[5] = 0;
7534 r_bloomstate.screentexcoord2f[6] = 0;
7535 r_bloomstate.screentexcoord2f[7] = 0;
7537 // set up a texcoord array for the reduced resolution bloom image
7538 // (which will be additive blended over the screen image)
7539 r_bloomstate.bloomtexcoord2f[0] = 0;
7540 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7541 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7542 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7543 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7544 r_bloomstate.bloomtexcoord2f[5] = 0;
7545 r_bloomstate.bloomtexcoord2f[6] = 0;
7546 r_bloomstate.bloomtexcoord2f[7] = 0;
7548 if (r_hdr.integer || r_bloom.integer)
7550 r_bloomstate.enabled = true;
7551 r_bloomstate.hdr = r_hdr.integer != 0;
7554 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);
7557 void R_Bloom_CopyBloomTexture(float colorscale)
7559 r_refdef.stats.bloom++;
7561 // scale down screen texture to the bloom texture size
7563 R_SetViewport(&r_bloomstate.viewport);
7564 GL_BlendFunc(GL_ONE, GL_ZERO);
7565 GL_Color(colorscale, colorscale, colorscale, 1);
7566 // TODO: optimize with multitexture or GLSL
7567 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7568 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7569 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7570 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7572 // we now have a bloom image in the framebuffer
7573 // copy it into the bloom image texture for later processing
7574 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);
7575 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7578 void R_Bloom_CopyHDRTexture(void)
7580 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);
7581 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7584 void R_Bloom_MakeTexture(void)
7587 float xoffset, yoffset, r, brighten;
7589 r_refdef.stats.bloom++;
7591 R_ResetViewRendering2D();
7592 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7593 R_Mesh_ColorPointer(NULL, 0, 0);
7595 // we have a bloom image in the framebuffer
7597 R_SetViewport(&r_bloomstate.viewport);
7599 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7602 r = bound(0, r_bloom_colorexponent.value / x, 1);
7603 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7604 GL_Color(r, r, r, 1);
7605 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7606 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7607 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7608 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7610 // copy the vertically blurred bloom view to a texture
7611 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);
7612 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7615 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7616 brighten = r_bloom_brighten.value;
7618 brighten *= r_hdr_range.value;
7619 brighten = sqrt(brighten);
7621 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7622 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7623 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7625 for (dir = 0;dir < 2;dir++)
7627 // blend on at multiple vertical offsets to achieve a vertical blur
7628 // TODO: do offset blends using GLSL
7629 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7630 GL_BlendFunc(GL_ONE, GL_ZERO);
7631 for (x = -range;x <= range;x++)
7633 if (!dir){xoffset = 0;yoffset = x;}
7634 else {xoffset = x;yoffset = 0;}
7635 xoffset /= (float)r_bloomstate.bloomtexturewidth;
7636 yoffset /= (float)r_bloomstate.bloomtextureheight;
7637 // compute a texcoord array with the specified x and y offset
7638 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7639 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7640 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7641 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7642 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7643 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7644 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7645 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7646 // this r value looks like a 'dot' particle, fading sharply to
7647 // black at the edges
7648 // (probably not realistic but looks good enough)
7649 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7650 //r = brighten/(range*2+1);
7651 r = brighten / (range * 2 + 1);
7653 r *= (1 - x*x/(float)(range*range));
7654 GL_Color(r, r, r, 1);
7655 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7656 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7657 GL_BlendFunc(GL_ONE, GL_ONE);
7660 // copy the vertically blurred bloom view to a texture
7661 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7662 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7665 // apply subtract last
7666 // (just like it would be in a GLSL shader)
7667 if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7669 GL_BlendFunc(GL_ONE, GL_ZERO);
7670 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7671 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7672 GL_Color(1, 1, 1, 1);
7673 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7674 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7676 GL_BlendFunc(GL_ONE, GL_ONE);
7677 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7678 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7679 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7680 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7681 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7682 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7683 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7685 // copy the darkened bloom view to a texture
7686 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);
7687 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7691 void R_HDR_RenderBloomTexture(void)
7693 int oldwidth, oldheight;
7694 float oldcolorscale;
7696 oldcolorscale = r_refdef.view.colorscale;
7697 oldwidth = r_refdef.view.width;
7698 oldheight = r_refdef.view.height;
7699 r_refdef.view.width = r_bloomstate.bloomwidth;
7700 r_refdef.view.height = r_bloomstate.bloomheight;
7702 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
7703 // TODO: add exposure compensation features
7704 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7706 r_refdef.view.showdebug = false;
7707 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7709 R_ResetViewRendering3D();
7711 R_ClearScreen(r_refdef.fogenabled);
7712 if (r_timereport_active)
7713 R_TimeReport("HDRclear");
7716 if (r_timereport_active)
7717 R_TimeReport("visibility");
7719 // only do secondary renders with HDR if r_hdr is 2 or higher
7720 r_waterstate.numwaterplanes = 0;
7721 if (r_waterstate.enabled && r_hdr.integer >= 2)
7722 R_RenderWaterPlanes();
7724 r_refdef.view.showdebug = true;
7726 r_waterstate.numwaterplanes = 0;
7728 R_ResetViewRendering2D();
7730 R_Bloom_CopyHDRTexture();
7731 R_Bloom_MakeTexture();
7733 // restore the view settings
7734 r_refdef.view.width = oldwidth;
7735 r_refdef.view.height = oldheight;
7736 r_refdef.view.colorscale = oldcolorscale;
7738 R_ResetViewRendering3D();
7740 R_ClearScreen(r_refdef.fogenabled);
7741 if (r_timereport_active)
7742 R_TimeReport("viewclear");
7745 static void R_BlendView(void)
7747 unsigned int permutation;
7748 float uservecs[4][4];
7750 switch (vid.renderpath)
7752 case RENDERPATH_GL20:
7753 case RENDERPATH_CGGL:
7755 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7756 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7757 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7758 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7759 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7761 if (r_bloomstate.texture_screen)
7763 // make sure the buffer is available
7764 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7766 R_ResetViewRendering2D();
7767 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7768 R_Mesh_ColorPointer(NULL, 0, 0);
7770 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7772 // declare variables
7774 static float avgspeed;
7776 speed = VectorLength(cl.movement_velocity);
7778 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7779 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7781 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7782 speed = bound(0, speed, 1);
7783 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7785 // calculate values into a standard alpha
7786 cl.motionbluralpha = 1 - exp(-
7788 (r_motionblur.value * speed / 80)
7790 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7793 max(0.0001, cl.time - cl.oldtime) // fps independent
7796 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7797 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7799 if (cl.motionbluralpha > 0)
7801 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7802 GL_Color(1, 1, 1, cl.motionbluralpha);
7803 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7804 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7805 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7806 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7810 // copy view into the screen texture
7811 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);
7812 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7814 else if (!r_bloomstate.texture_bloom)
7816 // we may still have to do view tint...
7817 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7819 // apply a color tint to the whole view
7820 R_ResetViewRendering2D();
7821 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7822 R_Mesh_ColorPointer(NULL, 0, 0);
7823 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7824 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7825 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7826 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7828 break; // no screen processing, no bloom, skip it
7831 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7833 // render simple bloom effect
7834 // copy the screen and shrink it and darken it for the bloom process
7835 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7836 // make the bloom texture
7837 R_Bloom_MakeTexture();
7840 #if _MSC_VER >= 1400
7841 #define sscanf sscanf_s
7843 memset(uservecs, 0, sizeof(uservecs));
7844 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7845 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7846 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7847 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7849 R_ResetViewRendering2D();
7850 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7851 R_Mesh_ColorPointer(NULL, 0, 0);
7852 GL_Color(1, 1, 1, 1);
7853 GL_BlendFunc(GL_ONE, GL_ZERO);
7854 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7855 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7857 switch(vid.renderpath)
7859 case RENDERPATH_GL20:
7860 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7861 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
7862 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
7863 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7864 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]);
7865 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7866 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]);
7867 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]);
7868 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]);
7869 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]);
7870 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7871 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7873 case RENDERPATH_CGGL:
7875 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7876 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
7877 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
7878 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
7879 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
7880 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7881 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
7882 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
7883 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
7884 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
7885 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
7886 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7892 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7893 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7895 case RENDERPATH_GL13:
7896 case RENDERPATH_GL11:
7897 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7899 // apply a color tint to the whole view
7900 R_ResetViewRendering2D();
7901 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7902 R_Mesh_ColorPointer(NULL, 0, 0);
7903 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7904 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7905 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7906 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7912 matrix4x4_t r_waterscrollmatrix;
7914 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7916 if (r_refdef.fog_density)
7918 r_refdef.fogcolor[0] = r_refdef.fog_red;
7919 r_refdef.fogcolor[1] = r_refdef.fog_green;
7920 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7922 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7923 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7924 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7925 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7929 VectorCopy(r_refdef.fogcolor, fogvec);
7930 // color.rgb *= ContrastBoost * SceneBrightness;
7931 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7932 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7933 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7934 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7939 void R_UpdateVariables(void)
7943 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7945 r_refdef.farclip = r_farclip_base.value;
7946 if (r_refdef.scene.worldmodel)
7947 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7948 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7950 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7951 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7952 r_refdef.polygonfactor = 0;
7953 r_refdef.polygonoffset = 0;
7954 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7955 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7957 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7958 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7959 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7960 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7961 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7962 if (r_showsurfaces.integer)
7964 r_refdef.scene.rtworld = false;
7965 r_refdef.scene.rtworldshadows = false;
7966 r_refdef.scene.rtdlight = false;
7967 r_refdef.scene.rtdlightshadows = false;
7968 r_refdef.lightmapintensity = 0;
7971 if (gamemode == GAME_NEHAHRA)
7973 if (gl_fogenable.integer)
7975 r_refdef.oldgl_fogenable = true;
7976 r_refdef.fog_density = gl_fogdensity.value;
7977 r_refdef.fog_red = gl_fogred.value;
7978 r_refdef.fog_green = gl_foggreen.value;
7979 r_refdef.fog_blue = gl_fogblue.value;
7980 r_refdef.fog_alpha = 1;
7981 r_refdef.fog_start = 0;
7982 r_refdef.fog_end = gl_skyclip.value;
7983 r_refdef.fog_height = 1<<30;
7984 r_refdef.fog_fadedepth = 128;
7986 else if (r_refdef.oldgl_fogenable)
7988 r_refdef.oldgl_fogenable = false;
7989 r_refdef.fog_density = 0;
7990 r_refdef.fog_red = 0;
7991 r_refdef.fog_green = 0;
7992 r_refdef.fog_blue = 0;
7993 r_refdef.fog_alpha = 0;
7994 r_refdef.fog_start = 0;
7995 r_refdef.fog_end = 0;
7996 r_refdef.fog_height = 1<<30;
7997 r_refdef.fog_fadedepth = 128;
8001 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8002 r_refdef.fog_start = max(0, r_refdef.fog_start);
8003 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8005 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8007 if (r_refdef.fog_density && r_drawfog.integer)
8009 r_refdef.fogenabled = true;
8010 // this is the point where the fog reaches 0.9986 alpha, which we
8011 // consider a good enough cutoff point for the texture
8012 // (0.9986 * 256 == 255.6)
8013 if (r_fog_exp2.integer)
8014 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8016 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8017 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8018 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8019 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8020 // fog color was already set
8021 // update the fog texture
8022 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)
8023 R_BuildFogTexture();
8026 r_refdef.fogenabled = false;
8028 switch(vid.renderpath)
8030 case RENDERPATH_GL20:
8031 case RENDERPATH_CGGL:
8032 if(v_glslgamma.integer && !vid_gammatables_trivial)
8034 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8036 // build GLSL gamma texture
8037 #define RAMPWIDTH 256
8038 unsigned short ramp[RAMPWIDTH * 3];
8039 unsigned char rampbgr[RAMPWIDTH][4];
8042 r_texture_gammaramps_serial = vid_gammatables_serial;
8044 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8045 for(i = 0; i < RAMPWIDTH; ++i)
8047 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8048 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8049 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8052 if (r_texture_gammaramps)
8054 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8058 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);
8064 // remove GLSL gamma texture
8067 case RENDERPATH_GL13:
8068 case RENDERPATH_GL11:
8073 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8074 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8080 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8081 if( scenetype != r_currentscenetype ) {
8082 // store the old scenetype
8083 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8084 r_currentscenetype = scenetype;
8085 // move in the new scene
8086 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8095 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8097 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8098 if( scenetype == r_currentscenetype ) {
8099 return &r_refdef.scene;
8101 return &r_scenes_store[ scenetype ];
8110 void R_RenderView(void)
8112 if (r_timereport_active)
8113 R_TimeReport("start");
8114 r_textureframe++; // used only by R_GetCurrentTexture
8115 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8117 if (!r_drawentities.integer)
8118 r_refdef.scene.numentities = 0;
8120 R_AnimCache_ClearCache();
8121 R_FrameData_NewFrame();
8123 if (r_refdef.view.isoverlay)
8125 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8126 GL_Clear( GL_DEPTH_BUFFER_BIT );
8127 R_TimeReport("depthclear");
8129 r_refdef.view.showdebug = false;
8131 r_waterstate.enabled = false;
8132 r_waterstate.numwaterplanes = 0;
8140 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8141 return; //Host_Error ("R_RenderView: NULL worldmodel");
8143 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8145 // break apart the view matrix into vectors for various purposes
8146 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8147 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8148 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8149 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8150 // make an inverted copy of the view matrix for tracking sprites
8151 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8153 R_Shadow_UpdateWorldLightSelection();
8155 R_Bloom_StartFrame();
8156 R_Water_StartFrame();
8159 if (r_timereport_active)
8160 R_TimeReport("viewsetup");
8162 R_ResetViewRendering3D();
8164 if (r_refdef.view.clear || r_refdef.fogenabled)
8166 R_ClearScreen(r_refdef.fogenabled);
8167 if (r_timereport_active)
8168 R_TimeReport("viewclear");
8170 r_refdef.view.clear = true;
8172 // this produces a bloom texture to be used in R_BlendView() later
8173 if (r_hdr.integer && r_bloomstate.bloomwidth)
8175 R_HDR_RenderBloomTexture();
8176 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8177 r_textureframe++; // used only by R_GetCurrentTexture
8180 r_refdef.view.showdebug = true;
8183 if (r_timereport_active)
8184 R_TimeReport("visibility");
8186 r_waterstate.numwaterplanes = 0;
8187 if (r_waterstate.enabled)
8188 R_RenderWaterPlanes();
8191 r_waterstate.numwaterplanes = 0;
8194 if (r_timereport_active)
8195 R_TimeReport("blendview");
8197 GL_Scissor(0, 0, vid.width, vid.height);
8198 GL_ScissorTest(false);
8202 void R_RenderWaterPlanes(void)
8204 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8206 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8207 if (r_timereport_active)
8208 R_TimeReport("waterworld");
8211 // don't let sound skip if going slow
8212 if (r_refdef.scene.extraupdate)
8215 R_DrawModelsAddWaterPlanes();
8216 if (r_timereport_active)
8217 R_TimeReport("watermodels");
8219 if (r_waterstate.numwaterplanes)
8221 R_Water_ProcessPlanes();
8222 if (r_timereport_active)
8223 R_TimeReport("waterscenes");
8227 extern void R_DrawLightningBeams (void);
8228 extern void VM_CL_AddPolygonsToMeshQueue (void);
8229 extern void R_DrawPortals (void);
8230 extern cvar_t cl_locs_show;
8231 static void R_DrawLocs(void);
8232 static void R_DrawEntityBBoxes(void);
8233 static void R_DrawModelDecals(void);
8234 extern void R_DrawModelShadows(void);
8235 extern void R_DrawModelShadowMaps(void);
8236 extern cvar_t cl_decals_newsystem;
8237 extern qboolean r_shadow_usingdeferredprepass;
8238 void R_RenderScene(void)
8240 qboolean shadowmapping = false;
8242 r_refdef.stats.renders++;
8246 // don't let sound skip if going slow
8247 if (r_refdef.scene.extraupdate)
8250 R_MeshQueue_BeginScene();
8254 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);
8256 if (cl.csqc_vidvars.drawworld)
8258 // don't let sound skip if going slow
8259 if (r_refdef.scene.extraupdate)
8262 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8264 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8265 if (r_timereport_active)
8266 R_TimeReport("worldsky");
8269 if (R_DrawBrushModelsSky() && r_timereport_active)
8270 R_TimeReport("bmodelsky");
8272 if (skyrendermasked && skyrenderlater)
8274 // we have to force off the water clipping plane while rendering sky
8278 if (r_timereport_active)
8279 R_TimeReport("sky");
8283 R_AnimCache_CacheVisibleEntities();
8284 if (r_timereport_active)
8285 R_TimeReport("animation");
8287 R_Shadow_PrepareLights();
8288 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8289 R_Shadow_PrepareModelShadows();
8290 if (r_timereport_active)
8291 R_TimeReport("preparelights");
8293 if (R_Shadow_ShadowMappingEnabled())
8294 shadowmapping = true;
8296 if (r_shadow_usingdeferredprepass)
8297 R_Shadow_DrawPrepass();
8299 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8301 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8302 if (r_timereport_active)
8303 R_TimeReport("worlddepth");
8305 if (r_depthfirst.integer >= 2)
8307 R_DrawModelsDepth();
8308 if (r_timereport_active)
8309 R_TimeReport("modeldepth");
8312 if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8314 R_DrawModelShadowMaps();
8315 R_ResetViewRendering3D();
8316 // don't let sound skip if going slow
8317 if (r_refdef.scene.extraupdate)
8321 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8323 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8324 if (r_timereport_active)
8325 R_TimeReport("world");
8328 // don't let sound skip if going slow
8329 if (r_refdef.scene.extraupdate)
8333 if (r_timereport_active)
8334 R_TimeReport("models");
8336 // don't let sound skip if going slow
8337 if (r_refdef.scene.extraupdate)
8340 if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8342 R_DrawModelShadows();
8343 R_ResetViewRendering3D();
8344 // don't let sound skip if going slow
8345 if (r_refdef.scene.extraupdate)
8349 if (!r_shadow_usingdeferredprepass)
8351 R_Shadow_DrawLights();
8352 if (r_timereport_active)
8353 R_TimeReport("rtlights");
8356 // don't let sound skip if going slow
8357 if (r_refdef.scene.extraupdate)
8360 if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8362 R_DrawModelShadows();
8363 R_ResetViewRendering3D();
8364 // don't let sound skip if going slow
8365 if (r_refdef.scene.extraupdate)
8369 if (cl.csqc_vidvars.drawworld)
8371 if (cl_decals_newsystem.integer)
8373 R_DrawModelDecals();
8374 if (r_timereport_active)
8375 R_TimeReport("modeldecals");
8380 if (r_timereport_active)
8381 R_TimeReport("decals");
8385 if (r_timereport_active)
8386 R_TimeReport("particles");
8389 if (r_timereport_active)
8390 R_TimeReport("explosions");
8392 R_DrawLightningBeams();
8393 if (r_timereport_active)
8394 R_TimeReport("lightning");
8397 VM_CL_AddPolygonsToMeshQueue();
8399 if (r_refdef.view.showdebug)
8401 if (cl_locs_show.integer)
8404 if (r_timereport_active)
8405 R_TimeReport("showlocs");
8408 if (r_drawportals.integer)
8411 if (r_timereport_active)
8412 R_TimeReport("portals");
8415 if (r_showbboxes.value > 0)
8417 R_DrawEntityBBoxes();
8418 if (r_timereport_active)
8419 R_TimeReport("bboxes");
8423 R_MeshQueue_RenderTransparent();
8424 if (r_timereport_active)
8425 R_TimeReport("drawtrans");
8427 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))
8429 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8430 if (r_timereport_active)
8431 R_TimeReport("worlddebug");
8432 R_DrawModelsDebug();
8433 if (r_timereport_active)
8434 R_TimeReport("modeldebug");
8437 if (cl.csqc_vidvars.drawworld)
8439 R_Shadow_DrawCoronas();
8440 if (r_timereport_active)
8441 R_TimeReport("coronas");
8444 // don't let sound skip if going slow
8445 if (r_refdef.scene.extraupdate)
8448 R_ResetViewRendering2D();
8451 static const unsigned short bboxelements[36] =
8461 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8464 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8466 RSurf_ActiveWorldEntity();
8468 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8469 GL_DepthMask(false);
8470 GL_DepthRange(0, 1);
8471 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8472 R_Mesh_ResetTextureState();
8474 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8475 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8476 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8477 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8478 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8479 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8480 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8481 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8482 R_FillColors(color4f, 8, cr, cg, cb, ca);
8483 if (r_refdef.fogenabled)
8485 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8487 f1 = RSurf_FogVertex(v);
8489 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8490 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8491 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8494 R_Mesh_VertexPointer(vertex3f, 0, 0);
8495 R_Mesh_ColorPointer(color4f, 0, 0);
8496 R_Mesh_ResetTextureState();
8497 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8498 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8501 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8505 prvm_edict_t *edict;
8506 prvm_prog_t *prog_save = prog;
8508 // this function draws bounding boxes of server entities
8512 GL_CullFace(GL_NONE);
8513 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8517 for (i = 0;i < numsurfaces;i++)
8519 edict = PRVM_EDICT_NUM(surfacelist[i]);
8520 switch ((int)edict->fields.server->solid)
8522 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
8523 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
8524 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
8525 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8526 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
8527 default: Vector4Set(color, 0, 0, 0, 0.50);break;
8529 color[3] *= r_showbboxes.value;
8530 color[3] = bound(0, color[3], 1);
8531 GL_DepthTest(!r_showdisabledepthtest.integer);
8532 GL_CullFace(r_refdef.view.cullface_front);
8533 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8539 static void R_DrawEntityBBoxes(void)
8542 prvm_edict_t *edict;
8544 prvm_prog_t *prog_save = prog;
8546 // this function draws bounding boxes of server entities
8552 for (i = 0;i < prog->num_edicts;i++)
8554 edict = PRVM_EDICT_NUM(i);
8555 if (edict->priv.server->free)
8557 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8558 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8560 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8562 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8563 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8569 static const int nomodelelement3i[24] =
8581 static const unsigned short nomodelelement3s[24] =
8593 static const float nomodelvertex3f[6*3] =
8603 static const float nomodelcolor4f[6*4] =
8605 0.0f, 0.0f, 0.5f, 1.0f,
8606 0.0f, 0.0f, 0.5f, 1.0f,
8607 0.0f, 0.5f, 0.0f, 1.0f,
8608 0.0f, 0.5f, 0.0f, 1.0f,
8609 0.5f, 0.0f, 0.0f, 1.0f,
8610 0.5f, 0.0f, 0.0f, 1.0f
8613 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8619 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);
8621 // this is only called once per entity so numsurfaces is always 1, and
8622 // surfacelist is always {0}, so this code does not handle batches
8624 if (rsurface.ent_flags & RENDER_ADDITIVE)
8626 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8627 GL_DepthMask(false);
8629 else if (rsurface.colormod[3] < 1)
8631 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8632 GL_DepthMask(false);
8636 GL_BlendFunc(GL_ONE, GL_ZERO);
8639 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8640 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8641 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8642 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8643 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8644 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8645 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8646 R_Mesh_ColorPointer(color4f, 0, 0);
8647 for (i = 0, c = color4f;i < 6;i++, c += 4)
8649 c[0] *= rsurface.colormod[0];
8650 c[1] *= rsurface.colormod[1];
8651 c[2] *= rsurface.colormod[2];
8652 c[3] *= rsurface.colormod[3];
8654 if (r_refdef.fogenabled)
8656 for (i = 0, c = color4f;i < 6;i++, c += 4)
8658 f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8660 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8661 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8662 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8665 R_Mesh_ResetTextureState();
8666 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8669 void R_DrawNoModel(entity_render_t *ent)
8672 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8673 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8674 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8676 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8679 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8681 vec3_t right1, right2, diff, normal;
8683 VectorSubtract (org2, org1, normal);
8685 // calculate 'right' vector for start
8686 VectorSubtract (r_refdef.view.origin, org1, diff);
8687 CrossProduct (normal, diff, right1);
8688 VectorNormalize (right1);
8690 // calculate 'right' vector for end
8691 VectorSubtract (r_refdef.view.origin, org2, diff);
8692 CrossProduct (normal, diff, right2);
8693 VectorNormalize (right2);
8695 vert[ 0] = org1[0] + width * right1[0];
8696 vert[ 1] = org1[1] + width * right1[1];
8697 vert[ 2] = org1[2] + width * right1[2];
8698 vert[ 3] = org1[0] - width * right1[0];
8699 vert[ 4] = org1[1] - width * right1[1];
8700 vert[ 5] = org1[2] - width * right1[2];
8701 vert[ 6] = org2[0] - width * right2[0];
8702 vert[ 7] = org2[1] - width * right2[1];
8703 vert[ 8] = org2[2] - width * right2[2];
8704 vert[ 9] = org2[0] + width * right2[0];
8705 vert[10] = org2[1] + width * right2[1];
8706 vert[11] = org2[2] + width * right2[2];
8709 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)
8711 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8712 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8713 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8714 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8715 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8716 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8717 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8718 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8719 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8720 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8721 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8722 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8725 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8730 VectorSet(v, x, y, z);
8731 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8732 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8734 if (i == mesh->numvertices)
8736 if (mesh->numvertices < mesh->maxvertices)
8738 VectorCopy(v, vertex3f);
8739 mesh->numvertices++;
8741 return mesh->numvertices;
8747 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8751 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8752 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8753 e = mesh->element3i + mesh->numtriangles * 3;
8754 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8756 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8757 if (mesh->numtriangles < mesh->maxtriangles)
8762 mesh->numtriangles++;
8764 element[1] = element[2];
8768 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8772 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8773 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8774 e = mesh->element3i + mesh->numtriangles * 3;
8775 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8777 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8778 if (mesh->numtriangles < mesh->maxtriangles)
8783 mesh->numtriangles++;
8785 element[1] = element[2];
8789 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8790 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8792 int planenum, planenum2;
8795 mplane_t *plane, *plane2;
8797 double temppoints[2][256*3];
8798 // figure out how large a bounding box we need to properly compute this brush
8800 for (w = 0;w < numplanes;w++)
8801 maxdist = max(maxdist, fabs(planes[w].dist));
8802 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8803 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8804 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8808 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8809 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8811 if (planenum2 == planenum)
8813 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);
8816 if (tempnumpoints < 3)
8818 // generate elements forming a triangle fan for this polygon
8819 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8823 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)
8825 texturelayer_t *layer;
8826 layer = t->currentlayers + t->currentnumlayers++;
8828 layer->depthmask = depthmask;
8829 layer->blendfunc1 = blendfunc1;
8830 layer->blendfunc2 = blendfunc2;
8831 layer->texture = texture;
8832 layer->texmatrix = *matrix;
8833 layer->color[0] = r;
8834 layer->color[1] = g;
8835 layer->color[2] = b;
8836 layer->color[3] = a;
8839 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8842 index = parms[2] + r_refdef.scene.time * parms[3];
8843 index -= floor(index);
8847 case Q3WAVEFUNC_NONE:
8848 case Q3WAVEFUNC_NOISE:
8849 case Q3WAVEFUNC_COUNT:
8852 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8853 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8854 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8855 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8856 case Q3WAVEFUNC_TRIANGLE:
8858 f = index - floor(index);
8869 return (float)(parms[0] + parms[1] * f);
8872 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8877 matrix4x4_t matrix, temp;
8878 switch(tcmod->tcmod)
8882 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8883 matrix = r_waterscrollmatrix;
8885 matrix = identitymatrix;
8887 case Q3TCMOD_ENTITYTRANSLATE:
8888 // this is used in Q3 to allow the gamecode to control texcoord
8889 // scrolling on the entity, which is not supported in darkplaces yet.
8890 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8892 case Q3TCMOD_ROTATE:
8893 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8894 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8895 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8898 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8900 case Q3TCMOD_SCROLL:
8901 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8903 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8904 w = (int) tcmod->parms[0];
8905 h = (int) tcmod->parms[1];
8906 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8908 idx = (int) floor(f * w * h);
8909 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8911 case Q3TCMOD_STRETCH:
8912 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8913 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8915 case Q3TCMOD_TRANSFORM:
8916 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8917 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8918 VectorSet(tcmat + 6, 0 , 0 , 1);
8919 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8920 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8922 case Q3TCMOD_TURBULENT:
8923 // this is handled in the RSurf_PrepareVertices function
8924 matrix = identitymatrix;
8928 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8931 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8933 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8934 char name[MAX_QPATH];
8935 skinframe_t *skinframe;
8936 unsigned char pixels[296*194];
8937 strlcpy(cache->name, skinname, sizeof(cache->name));
8938 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8939 if (developer_loading.integer)
8940 Con_Printf("loading %s\n", name);
8941 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8942 if (!skinframe || !skinframe->base)
8945 fs_offset_t filesize;
8947 f = FS_LoadFile(name, tempmempool, true, &filesize);
8950 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8951 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8955 cache->skinframe = skinframe;
8958 texture_t *R_GetCurrentTexture(texture_t *t)
8961 const entity_render_t *ent = rsurface.entity;
8962 dp_model_t *model = ent->model;
8963 q3shaderinfo_layer_tcmod_t *tcmod;
8965 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8966 return t->currentframe;
8967 t->update_lastrenderframe = r_textureframe;
8968 t->update_lastrenderentity = (void *)ent;
8970 // switch to an alternate material if this is a q1bsp animated material
8972 texture_t *texture = t;
8973 int s = rsurface.ent_skinnum;
8974 if ((unsigned int)s >= (unsigned int)model->numskins)
8976 if (model->skinscenes)
8978 if (model->skinscenes[s].framecount > 1)
8979 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8981 s = model->skinscenes[s].firstframe;
8984 t = t + s * model->num_surfaces;
8987 // use an alternate animation if the entity's frame is not 0,
8988 // and only if the texture has an alternate animation
8989 if (rsurface.ent_alttextures && t->anim_total[1])
8990 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8992 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8994 texture->currentframe = t;
8997 // update currentskinframe to be a qw skin or animation frame
8998 if (rsurface.ent_qwskin >= 0)
9000 i = rsurface.ent_qwskin;
9001 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9003 r_qwskincache_size = cl.maxclients;
9005 Mem_Free(r_qwskincache);
9006 r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9008 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9009 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9010 t->currentskinframe = r_qwskincache[i].skinframe;
9011 if (t->currentskinframe == NULL)
9012 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9014 else if (t->numskinframes >= 2)
9015 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9016 if (t->backgroundnumskinframes >= 2)
9017 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9019 t->currentmaterialflags = t->basematerialflags;
9020 t->currentalpha = rsurface.colormod[3];
9021 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9022 t->currentalpha *= r_wateralpha.value;
9023 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9024 t->currentalpha *= t->r_water_wateralpha;
9025 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9026 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9027 if (!(rsurface.ent_flags & RENDER_LIGHT))
9028 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9029 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9031 // pick a model lighting mode
9032 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9033 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9035 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9037 if (rsurface.ent_flags & RENDER_ADDITIVE)
9038 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9039 else if (t->currentalpha < 1)
9040 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9041 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9042 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9043 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9044 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9045 if (t->backgroundnumskinframes)
9046 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9047 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9049 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9050 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9053 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9054 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9055 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9057 // there is no tcmod
9058 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9060 t->currenttexmatrix = r_waterscrollmatrix;
9061 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9063 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9065 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9066 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9069 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9070 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9071 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9072 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9074 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9075 if (t->currentskinframe->qpixels)
9076 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9077 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9078 if (!t->basetexture)
9079 t->basetexture = r_texture_notexture;
9080 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9081 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9082 t->nmaptexture = t->currentskinframe->nmap;
9083 if (!t->nmaptexture)
9084 t->nmaptexture = r_texture_blanknormalmap;
9085 t->glosstexture = r_texture_black;
9086 t->glowtexture = t->currentskinframe->glow;
9087 t->fogtexture = t->currentskinframe->fog;
9088 t->reflectmasktexture = t->currentskinframe->reflect;
9089 if (t->backgroundnumskinframes)
9091 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9092 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9093 t->backgroundglosstexture = r_texture_black;
9094 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9095 if (!t->backgroundnmaptexture)
9096 t->backgroundnmaptexture = r_texture_blanknormalmap;
9100 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9101 t->backgroundnmaptexture = r_texture_blanknormalmap;
9102 t->backgroundglosstexture = r_texture_black;
9103 t->backgroundglowtexture = NULL;
9105 t->specularpower = r_shadow_glossexponent.value;
9106 // TODO: store reference values for these in the texture?
9107 t->specularscale = 0;
9108 if (r_shadow_gloss.integer > 0)
9110 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9112 if (r_shadow_glossintensity.value > 0)
9114 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9115 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9116 t->specularscale = r_shadow_glossintensity.value;
9119 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9121 t->glosstexture = r_texture_white;
9122 t->backgroundglosstexture = r_texture_white;
9123 t->specularscale = r_shadow_gloss2intensity.value;
9124 t->specularpower = r_shadow_gloss2exponent.value;
9127 t->specularscale *= t->specularscalemod;
9128 t->specularpower *= t->specularpowermod;
9130 // lightmaps mode looks bad with dlights using actual texturing, so turn
9131 // off the colormap and glossmap, but leave the normalmap on as it still
9132 // accurately represents the shading involved
9133 if (gl_lightmaps.integer)
9135 t->basetexture = r_texture_grey128;
9136 t->pantstexture = r_texture_black;
9137 t->shirttexture = r_texture_black;
9138 t->nmaptexture = r_texture_blanknormalmap;
9139 t->glosstexture = r_texture_black;
9140 t->glowtexture = NULL;
9141 t->fogtexture = NULL;
9142 t->reflectmasktexture = NULL;
9143 t->backgroundbasetexture = NULL;
9144 t->backgroundnmaptexture = r_texture_blanknormalmap;
9145 t->backgroundglosstexture = r_texture_black;
9146 t->backgroundglowtexture = NULL;
9147 t->specularscale = 0;
9148 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9151 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9152 VectorClear(t->dlightcolor);
9153 t->currentnumlayers = 0;
9154 if (t->currentmaterialflags & MATERIALFLAG_WALL)
9156 int blendfunc1, blendfunc2;
9158 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9160 blendfunc1 = GL_SRC_ALPHA;
9161 blendfunc2 = GL_ONE;
9163 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9165 blendfunc1 = GL_SRC_ALPHA;
9166 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9168 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9170 blendfunc1 = t->customblendfunc[0];
9171 blendfunc2 = t->customblendfunc[1];
9175 blendfunc1 = GL_ONE;
9176 blendfunc2 = GL_ZERO;
9178 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9179 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9181 // fullbright is not affected by r_refdef.lightmapintensity
9182 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]);
9183 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9184 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]);
9185 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9186 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]);
9190 vec3_t ambientcolor;
9192 // set the color tint used for lights affecting this surface
9193 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9195 // q3bsp has no lightmap updates, so the lightstylevalue that
9196 // would normally be baked into the lightmap must be
9197 // applied to the color
9198 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9199 if (model->type == mod_brushq3)
9200 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9201 colorscale *= r_refdef.lightmapintensity;
9202 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9203 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9204 // basic lit geometry
9205 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]);
9206 // add pants/shirt if needed
9207 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9208 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]);
9209 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9210 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]);
9211 // now add ambient passes if needed
9212 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9214 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]);
9215 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9216 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]);
9217 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9218 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]);
9221 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9222 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]);
9223 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9225 // if this is opaque use alpha blend which will darken the earlier
9228 // if this is an alpha blended material, all the earlier passes
9229 // were darkened by fog already, so we only need to add the fog
9230 // color ontop through the fog mask texture
9232 // if this is an additive blended material, all the earlier passes
9233 // were darkened by fog already, and we should not add fog color
9234 // (because the background was not darkened, there is no fog color
9235 // that was lost behind it).
9236 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]);
9240 return t->currentframe;
9243 rsurfacestate_t rsurface;
9245 void R_Mesh_ResizeArrays(int newvertices)
9248 if (rsurface.array_size >= newvertices)
9250 if (rsurface.array_modelvertex3f)
9251 Mem_Free(rsurface.array_modelvertex3f);
9252 rsurface.array_size = (newvertices + 1023) & ~1023;
9253 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9254 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
9255 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
9256 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
9257 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
9258 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
9259 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9260 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9261 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
9262 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
9263 rsurface.array_color4f = base + rsurface.array_size * 27;
9264 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9267 void RSurf_ActiveWorldEntity(void)
9269 dp_model_t *model = r_refdef.scene.worldmodel;
9270 //if (rsurface.entity == r_refdef.scene.worldentity)
9272 rsurface.entity = r_refdef.scene.worldentity;
9273 rsurface.skeleton = NULL;
9274 rsurface.ent_skinnum = 0;
9275 rsurface.ent_qwskin = -1;
9276 rsurface.ent_shadertime = 0;
9277 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9278 if (rsurface.array_size < model->surfmesh.num_vertices)
9279 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9280 rsurface.matrix = identitymatrix;
9281 rsurface.inversematrix = identitymatrix;
9282 rsurface.matrixscale = 1;
9283 rsurface.inversematrixscale = 1;
9284 R_EntityMatrix(&identitymatrix);
9285 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9286 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9287 rsurface.fograngerecip = r_refdef.fograngerecip;
9288 rsurface.fogheightfade = r_refdef.fogheightfade;
9289 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9290 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9291 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9292 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9293 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9294 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9295 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9296 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9297 rsurface.colormod[3] = 1;
9298 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);
9299 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9300 rsurface.frameblend[0].lerp = 1;
9301 rsurface.ent_alttextures = false;
9302 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9303 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9304 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9305 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9306 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9307 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9308 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9309 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9310 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9311 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9312 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9313 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9314 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9315 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9316 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9317 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9318 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9319 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9320 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9321 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9322 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9323 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9324 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9325 rsurface.modelelement3i = model->surfmesh.data_element3i;
9326 rsurface.modelelement3s = model->surfmesh.data_element3s;
9327 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9328 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9329 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9330 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9331 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9332 rsurface.modelsurfaces = model->data_surfaces;
9333 rsurface.generatedvertex = false;
9334 rsurface.vertex3f = rsurface.modelvertex3f;
9335 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9336 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9337 rsurface.svector3f = rsurface.modelsvector3f;
9338 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9339 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9340 rsurface.tvector3f = rsurface.modeltvector3f;
9341 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9342 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9343 rsurface.normal3f = rsurface.modelnormal3f;
9344 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9345 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9346 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9349 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9351 dp_model_t *model = ent->model;
9352 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9354 rsurface.entity = (entity_render_t *)ent;
9355 rsurface.skeleton = ent->skeleton;
9356 rsurface.ent_skinnum = ent->skinnum;
9357 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;
9358 rsurface.ent_shadertime = ent->shadertime;
9359 rsurface.ent_flags = ent->flags;
9360 if (rsurface.array_size < model->surfmesh.num_vertices)
9361 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9362 rsurface.matrix = ent->matrix;
9363 rsurface.inversematrix = ent->inversematrix;
9364 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9365 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9366 R_EntityMatrix(&rsurface.matrix);
9367 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9368 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9369 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9370 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9371 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9372 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9373 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9374 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9375 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9376 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9377 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9378 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9379 rsurface.colormod[3] = ent->alpha;
9380 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9381 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9382 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9383 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9384 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9385 if (ent->model->brush.submodel && !prepass)
9387 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9388 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9390 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9392 if (ent->animcache_vertex3f && !r_framedata_failed)
9394 rsurface.modelvertex3f = ent->animcache_vertex3f;
9395 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9396 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9397 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9399 else if (wanttangents)
9401 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9402 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9403 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9404 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9405 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9407 else if (wantnormals)
9409 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9410 rsurface.modelsvector3f = NULL;
9411 rsurface.modeltvector3f = NULL;
9412 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9413 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9417 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9418 rsurface.modelsvector3f = NULL;
9419 rsurface.modeltvector3f = NULL;
9420 rsurface.modelnormal3f = NULL;
9421 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9423 rsurface.modelvertex3f_bufferobject = 0;
9424 rsurface.modelvertex3f_bufferoffset = 0;
9425 rsurface.modelsvector3f_bufferobject = 0;
9426 rsurface.modelsvector3f_bufferoffset = 0;
9427 rsurface.modeltvector3f_bufferobject = 0;
9428 rsurface.modeltvector3f_bufferoffset = 0;
9429 rsurface.modelnormal3f_bufferobject = 0;
9430 rsurface.modelnormal3f_bufferoffset = 0;
9431 rsurface.generatedvertex = true;
9435 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
9436 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9437 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9438 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9439 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9440 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9441 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9442 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9443 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9444 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
9445 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9446 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9447 rsurface.generatedvertex = false;
9449 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
9450 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9451 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9452 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
9453 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9454 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9455 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
9456 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9457 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9458 rsurface.modelelement3i = model->surfmesh.data_element3i;
9459 rsurface.modelelement3s = model->surfmesh.data_element3s;
9460 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9461 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9462 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9463 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9464 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9465 rsurface.modelsurfaces = model->data_surfaces;
9466 rsurface.vertex3f = rsurface.modelvertex3f;
9467 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9468 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9469 rsurface.svector3f = rsurface.modelsvector3f;
9470 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9471 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9472 rsurface.tvector3f = rsurface.modeltvector3f;
9473 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9474 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9475 rsurface.normal3f = rsurface.modelnormal3f;
9476 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9477 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9478 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9481 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)
9483 rsurface.entity = r_refdef.scene.worldentity;
9484 rsurface.skeleton = NULL;
9485 rsurface.ent_skinnum = 0;
9486 rsurface.ent_qwskin = -1;
9487 rsurface.ent_shadertime = shadertime;
9488 rsurface.ent_flags = entflags;
9489 rsurface.modelnum_vertices = numvertices;
9490 rsurface.modelnum_triangles = numtriangles;
9491 if (rsurface.array_size < rsurface.modelnum_vertices)
9492 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9493 rsurface.matrix = *matrix;
9494 rsurface.inversematrix = *inversematrix;
9495 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9496 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9497 R_EntityMatrix(&rsurface.matrix);
9498 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9499 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9500 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9501 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9502 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9503 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9504 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9505 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9506 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9507 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9508 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9509 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9510 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);
9511 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9512 rsurface.frameblend[0].lerp = 1;
9513 rsurface.ent_alttextures = false;
9514 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9515 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9518 rsurface.modelvertex3f = vertex3f;
9519 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9520 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9521 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9523 else if (wantnormals)
9525 rsurface.modelvertex3f = vertex3f;
9526 rsurface.modelsvector3f = NULL;
9527 rsurface.modeltvector3f = NULL;
9528 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9532 rsurface.modelvertex3f = vertex3f;
9533 rsurface.modelsvector3f = NULL;
9534 rsurface.modeltvector3f = NULL;
9535 rsurface.modelnormal3f = NULL;
9537 rsurface.modelvertex3f_bufferobject = 0;
9538 rsurface.modelvertex3f_bufferoffset = 0;
9539 rsurface.modelsvector3f_bufferobject = 0;
9540 rsurface.modelsvector3f_bufferoffset = 0;
9541 rsurface.modeltvector3f_bufferobject = 0;
9542 rsurface.modeltvector3f_bufferoffset = 0;
9543 rsurface.modelnormal3f_bufferobject = 0;
9544 rsurface.modelnormal3f_bufferoffset = 0;
9545 rsurface.generatedvertex = true;
9546 rsurface.modellightmapcolor4f = color4f;
9547 rsurface.modellightmapcolor4f_bufferobject = 0;
9548 rsurface.modellightmapcolor4f_bufferoffset = 0;
9549 rsurface.modeltexcoordtexture2f = texcoord2f;
9550 rsurface.modeltexcoordtexture2f_bufferobject = 0;
9551 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9552 rsurface.modeltexcoordlightmap2f = NULL;
9553 rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9554 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9555 rsurface.modelelement3i = element3i;
9556 rsurface.modelelement3s = element3s;
9557 rsurface.modelelement3i_bufferobject = 0;
9558 rsurface.modelelement3s_bufferobject = 0;
9559 rsurface.modellightmapoffsets = NULL;
9560 rsurface.modelsurfaces = NULL;
9561 rsurface.vertex3f = rsurface.modelvertex3f;
9562 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9563 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9564 rsurface.svector3f = rsurface.modelsvector3f;
9565 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9566 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9567 rsurface.tvector3f = rsurface.modeltvector3f;
9568 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9569 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9570 rsurface.normal3f = rsurface.modelnormal3f;
9571 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9572 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9573 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9575 if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9577 if ((wantnormals || wanttangents) && !normal3f)
9578 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9579 if (wanttangents && !svector3f)
9580 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);
9584 float RSurf_FogPoint(const float *v)
9586 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9587 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9588 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9589 float FogHeightFade = r_refdef.fogheightfade;
9591 unsigned int fogmasktableindex;
9592 if (r_refdef.fogplaneviewabove)
9593 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9595 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9596 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9597 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9600 float RSurf_FogVertex(const float *v)
9602 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9603 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9604 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9605 float FogHeightFade = rsurface.fogheightfade;
9607 unsigned int fogmasktableindex;
9608 if (r_refdef.fogplaneviewabove)
9609 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9611 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9612 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9613 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9616 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9617 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9620 int texturesurfaceindex;
9625 const float *v1, *in_tc;
9627 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9629 q3shaderinfo_deform_t *deform;
9630 // 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
9631 if (rsurface.generatedvertex)
9633 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9634 generatenormals = true;
9635 for (i = 0;i < Q3MAXDEFORMS;i++)
9637 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9639 generatetangents = true;
9640 generatenormals = true;
9642 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9643 generatenormals = true;
9645 if (generatenormals && !rsurface.modelnormal3f)
9647 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9648 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9649 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9650 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9652 if (generatetangents && !rsurface.modelsvector3f)
9654 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9655 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9656 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9657 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9658 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9659 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9660 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);
9663 rsurface.vertex3f = rsurface.modelvertex3f;
9664 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9665 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9666 rsurface.svector3f = rsurface.modelsvector3f;
9667 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9668 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9669 rsurface.tvector3f = rsurface.modeltvector3f;
9670 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9671 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9672 rsurface.normal3f = rsurface.modelnormal3f;
9673 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9674 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9675 // if vertices are deformed (sprite flares and things in maps, possibly
9676 // water waves, bulges and other deformations), generate them into
9677 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9678 // (may be static model data or generated data for an animated model, or
9679 // the previous deform pass)
9680 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9682 switch (deform->deform)
9685 case Q3DEFORM_PROJECTIONSHADOW:
9686 case Q3DEFORM_TEXT0:
9687 case Q3DEFORM_TEXT1:
9688 case Q3DEFORM_TEXT2:
9689 case Q3DEFORM_TEXT3:
9690 case Q3DEFORM_TEXT4:
9691 case Q3DEFORM_TEXT5:
9692 case Q3DEFORM_TEXT6:
9693 case Q3DEFORM_TEXT7:
9696 case Q3DEFORM_AUTOSPRITE:
9697 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9698 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9699 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9700 VectorNormalize(newforward);
9701 VectorNormalize(newright);
9702 VectorNormalize(newup);
9703 // make deformed versions of only the model vertices used by the specified surfaces
9704 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9706 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9707 // a single autosprite surface can contain multiple sprites...
9708 for (j = 0;j < surface->num_vertices - 3;j += 4)
9710 VectorClear(center);
9711 for (i = 0;i < 4;i++)
9712 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9713 VectorScale(center, 0.25f, center);
9714 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
9715 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9716 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9717 for (i = 0;i < 4;i++)
9719 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9720 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9723 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);
9724 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);
9726 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9727 rsurface.vertex3f_bufferobject = 0;
9728 rsurface.vertex3f_bufferoffset = 0;
9729 rsurface.svector3f = rsurface.array_deformedsvector3f;
9730 rsurface.svector3f_bufferobject = 0;
9731 rsurface.svector3f_bufferoffset = 0;
9732 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9733 rsurface.tvector3f_bufferobject = 0;
9734 rsurface.tvector3f_bufferoffset = 0;
9735 rsurface.normal3f = rsurface.array_deformednormal3f;
9736 rsurface.normal3f_bufferobject = 0;
9737 rsurface.normal3f_bufferoffset = 0;
9739 case Q3DEFORM_AUTOSPRITE2:
9740 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9741 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9742 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9743 VectorNormalize(newforward);
9744 VectorNormalize(newright);
9745 VectorNormalize(newup);
9746 // make deformed versions of only the model vertices used by the specified surfaces
9747 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9749 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9750 const float *v1, *v2;
9760 memset(shortest, 0, sizeof(shortest));
9761 // a single autosprite surface can contain multiple sprites...
9762 for (j = 0;j < surface->num_vertices - 3;j += 4)
9764 VectorClear(center);
9765 for (i = 0;i < 4;i++)
9766 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9767 VectorScale(center, 0.25f, center);
9768 // find the two shortest edges, then use them to define the
9769 // axis vectors for rotating around the central axis
9770 for (i = 0;i < 6;i++)
9772 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9773 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9775 Debug_PolygonBegin(NULL, 0);
9776 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9777 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);
9778 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9781 l = VectorDistance2(v1, v2);
9782 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9784 l += (1.0f / 1024.0f);
9785 if (shortest[0].length2 > l || i == 0)
9787 shortest[1] = shortest[0];
9788 shortest[0].length2 = l;
9789 shortest[0].v1 = v1;
9790 shortest[0].v2 = v2;
9792 else if (shortest[1].length2 > l || i == 1)
9794 shortest[1].length2 = l;
9795 shortest[1].v1 = v1;
9796 shortest[1].v2 = v2;
9799 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9800 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9802 Debug_PolygonBegin(NULL, 0);
9803 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9804 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);
9805 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9808 // this calculates the right vector from the shortest edge
9809 // and the up vector from the edge midpoints
9810 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9811 VectorNormalize(right);
9812 VectorSubtract(end, start, up);
9813 VectorNormalize(up);
9814 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9815 VectorSubtract(rsurface.localvieworigin, center, forward);
9816 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9817 VectorNegate(forward, forward);
9818 VectorReflect(forward, 0, up, forward);
9819 VectorNormalize(forward);
9820 CrossProduct(up, forward, newright);
9821 VectorNormalize(newright);
9823 Debug_PolygonBegin(NULL, 0);
9824 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);
9825 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9826 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9830 Debug_PolygonBegin(NULL, 0);
9831 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9832 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9833 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
9836 // rotate the quad around the up axis vector, this is made
9837 // especially easy by the fact we know the quad is flat,
9838 // so we only have to subtract the center position and
9839 // measure distance along the right vector, and then
9840 // multiply that by the newright vector and add back the
9842 // we also need to subtract the old position to undo the
9843 // displacement from the center, which we do with a
9844 // DotProduct, the subtraction/addition of center is also
9845 // optimized into DotProducts here
9846 l = DotProduct(right, center);
9847 for (i = 0;i < 4;i++)
9849 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9850 f = DotProduct(right, v1) - l;
9851 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9854 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);
9855 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);
9857 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9858 rsurface.vertex3f_bufferobject = 0;
9859 rsurface.vertex3f_bufferoffset = 0;
9860 rsurface.svector3f = rsurface.array_deformedsvector3f;
9861 rsurface.svector3f_bufferobject = 0;
9862 rsurface.svector3f_bufferoffset = 0;
9863 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9864 rsurface.tvector3f_bufferobject = 0;
9865 rsurface.tvector3f_bufferoffset = 0;
9866 rsurface.normal3f = rsurface.array_deformednormal3f;
9867 rsurface.normal3f_bufferobject = 0;
9868 rsurface.normal3f_bufferoffset = 0;
9870 case Q3DEFORM_NORMAL:
9871 // deform the normals to make reflections wavey
9872 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9874 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9875 for (j = 0;j < surface->num_vertices;j++)
9878 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
9879 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9880 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
9881 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9882 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9883 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9884 VectorNormalize(normal);
9886 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);
9888 rsurface.svector3f = rsurface.array_deformedsvector3f;
9889 rsurface.svector3f_bufferobject = 0;
9890 rsurface.svector3f_bufferoffset = 0;
9891 rsurface.tvector3f = rsurface.array_deformedtvector3f;
9892 rsurface.tvector3f_bufferobject = 0;
9893 rsurface.tvector3f_bufferoffset = 0;
9894 rsurface.normal3f = rsurface.array_deformednormal3f;
9895 rsurface.normal3f_bufferobject = 0;
9896 rsurface.normal3f_bufferoffset = 0;
9899 // deform vertex array to make wavey water and flags and such
9900 waveparms[0] = deform->waveparms[0];
9901 waveparms[1] = deform->waveparms[1];
9902 waveparms[2] = deform->waveparms[2];
9903 waveparms[3] = deform->waveparms[3];
9904 // this is how a divisor of vertex influence on deformation
9905 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9906 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9909 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9910 for (j = 0;j < surface->num_vertices;j++)
9912 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
9913 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
9914 // if the wavefunc depends on time, evaluate it per-vertex
9917 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9918 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9920 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
9923 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9924 rsurface.vertex3f_bufferobject = 0;
9925 rsurface.vertex3f_bufferoffset = 0;
9927 case Q3DEFORM_BULGE:
9928 // deform vertex array to make the surface have moving bulges
9929 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9931 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9932 for (j = 0;j < surface->num_vertices;j++)
9934 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9935 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9938 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9939 rsurface.vertex3f_bufferobject = 0;
9940 rsurface.vertex3f_bufferoffset = 0;
9943 // deform vertex array
9944 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9945 VectorScale(deform->parms, scale, waveparms);
9946 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9948 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9949 for (j = 0;j < surface->num_vertices;j++)
9950 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9952 rsurface.vertex3f = rsurface.array_deformedvertex3f;
9953 rsurface.vertex3f_bufferobject = 0;
9954 rsurface.vertex3f_bufferoffset = 0;
9958 // generate texcoords based on the chosen texcoord source
9959 switch(rsurface.texture->tcgen.tcgen)
9962 case Q3TCGEN_TEXTURE:
9963 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9964 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
9965 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9967 case Q3TCGEN_LIGHTMAP:
9968 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
9969 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9970 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9972 case Q3TCGEN_VECTOR:
9973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9975 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9976 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)
9978 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9979 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9982 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
9983 rsurface.texcoordtexture2f_bufferobject = 0;
9984 rsurface.texcoordtexture2f_bufferoffset = 0;
9986 case Q3TCGEN_ENVIRONMENT:
9987 // make environment reflections using a spheremap
9988 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9990 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9991 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9992 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9993 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9994 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9996 // identical to Q3A's method, but executed in worldspace so
9997 // carried models can be shiny too
9999 float viewer[3], d, reflected[3], worldreflected[3];
10001 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10002 // VectorNormalize(viewer);
10004 d = DotProduct(normal, viewer);
10006 reflected[0] = normal[0]*2*d - viewer[0];
10007 reflected[1] = normal[1]*2*d - viewer[1];
10008 reflected[2] = normal[2]*2*d - viewer[2];
10009 // note: this is proportinal to viewer, so we can normalize later
10011 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10012 VectorNormalize(worldreflected);
10014 // note: this sphere map only uses world x and z!
10015 // so positive and negative y will LOOK THE SAME.
10016 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10017 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10020 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10021 rsurface.texcoordtexture2f_bufferobject = 0;
10022 rsurface.texcoordtexture2f_bufferoffset = 0;
10025 // the only tcmod that needs software vertex processing is turbulent, so
10026 // check for it here and apply the changes if needed
10027 // and we only support that as the first one
10028 // (handling a mixture of turbulent and other tcmods would be problematic
10029 // without punting it entirely to a software path)
10030 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10032 amplitude = rsurface.texture->tcmods[0].parms[1];
10033 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10034 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10036 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10037 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)
10039 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10040 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10043 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
10044 rsurface.texcoordtexture2f_bufferobject = 0;
10045 rsurface.texcoordtexture2f_bufferoffset = 0;
10047 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10048 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10049 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10050 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10053 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10056 const msurface_t *surface = texturesurfacelist[0];
10057 const msurface_t *surface2;
10062 // TODO: lock all array ranges before render, rather than on each surface
10063 if (texturenumsurfaces == 1)
10064 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);
10065 else if (r_batchmode.integer == 2)
10067 #define MAXBATCHTRIANGLES 4096
10068 int batchtriangles = 0;
10069 static int batchelements[MAXBATCHTRIANGLES*3];
10070 for (i = 0;i < texturenumsurfaces;i = j)
10072 surface = texturesurfacelist[i];
10074 if (surface->num_triangles > MAXBATCHTRIANGLES)
10076 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);
10079 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10080 batchtriangles = surface->num_triangles;
10081 firstvertex = surface->num_firstvertex;
10082 endvertex = surface->num_firstvertex + surface->num_vertices;
10083 for (;j < texturenumsurfaces;j++)
10085 surface2 = texturesurfacelist[j];
10086 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10088 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10089 batchtriangles += surface2->num_triangles;
10090 firstvertex = min(firstvertex, surface2->num_firstvertex);
10091 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10093 surface2 = texturesurfacelist[j-1];
10094 numvertices = endvertex - firstvertex;
10095 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10098 else if (r_batchmode.integer == 1)
10100 for (i = 0;i < texturenumsurfaces;i = j)
10102 surface = texturesurfacelist[i];
10103 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10104 if (texturesurfacelist[j] != surface2)
10106 surface2 = texturesurfacelist[j-1];
10107 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10108 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10109 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10114 for (i = 0;i < texturenumsurfaces;i++)
10116 surface = texturesurfacelist[i];
10117 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);
10122 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10124 switch(vid.renderpath)
10126 case RENDERPATH_CGGL:
10128 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10129 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10132 case RENDERPATH_GL20:
10133 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10134 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10136 case RENDERPATH_GL13:
10137 case RENDERPATH_GL11:
10138 R_Mesh_TexBind(0, surface->lightmaptexture);
10143 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10145 // pick the closest matching water plane and bind textures
10146 int planeindex, vertexindex;
10150 r_waterstate_waterplane_t *p, *bestp;
10153 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10156 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10158 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10159 d += fabs(PlaneDiff(vert, &p->plane));
10161 if (bestd > d || !bestp)
10167 switch(vid.renderpath)
10169 case RENDERPATH_CGGL:
10171 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10172 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10175 case RENDERPATH_GL20:
10176 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10177 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10179 case RENDERPATH_GL13:
10180 case RENDERPATH_GL11:
10185 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10188 const msurface_t *surface;
10189 if (r_waterstate.renderingscene)
10191 for (i = 0;i < texturenumsurfaces;i++)
10193 surface = texturesurfacelist[i];
10194 RSurf_BindLightmapForSurface(surface);
10195 RSurf_BindReflectionForSurface(surface);
10196 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);
10200 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10204 const msurface_t *surface = texturesurfacelist[0];
10205 const msurface_t *surface2;
10210 if (texturenumsurfaces == 1)
10212 RSurf_BindLightmapForSurface(surface);
10213 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);
10215 else if (r_batchmode.integer == 2)
10217 #define MAXBATCHTRIANGLES 4096
10218 int batchtriangles = 0;
10219 static int batchelements[MAXBATCHTRIANGLES*3];
10220 for (i = 0;i < texturenumsurfaces;i = j)
10222 surface = texturesurfacelist[i];
10223 RSurf_BindLightmapForSurface(surface);
10225 if (surface->num_triangles > MAXBATCHTRIANGLES)
10227 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);
10230 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10231 batchtriangles = surface->num_triangles;
10232 firstvertex = surface->num_firstvertex;
10233 endvertex = surface->num_firstvertex + surface->num_vertices;
10234 for (;j < texturenumsurfaces;j++)
10236 surface2 = texturesurfacelist[j];
10237 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10239 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10240 batchtriangles += surface2->num_triangles;
10241 firstvertex = min(firstvertex, surface2->num_firstvertex);
10242 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10244 surface2 = texturesurfacelist[j-1];
10245 numvertices = endvertex - firstvertex;
10246 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10249 else if (r_batchmode.integer == 1)
10252 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10253 for (i = 0;i < texturenumsurfaces;i = j)
10255 surface = texturesurfacelist[i];
10256 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10257 if (texturesurfacelist[j] != surface2)
10259 Con_Printf(" %i", j - i);
10262 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10264 for (i = 0;i < texturenumsurfaces;i = j)
10266 surface = texturesurfacelist[i];
10267 RSurf_BindLightmapForSurface(surface);
10268 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10269 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10272 Con_Printf(" %i", j - i);
10274 surface2 = texturesurfacelist[j-1];
10275 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10276 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10277 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10285 for (i = 0;i < texturenumsurfaces;i++)
10287 surface = texturesurfacelist[i];
10288 RSurf_BindLightmapForSurface(surface);
10289 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);
10294 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10297 int texturesurfaceindex;
10298 if (r_showsurfaces.integer == 2)
10300 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10302 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10303 for (j = 0;j < surface->num_triangles;j++)
10305 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10306 GL_Color(f, f, f, 1);
10307 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10313 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10315 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10316 int k = (int)(((size_t)surface) / sizeof(msurface_t));
10317 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);
10318 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);
10323 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10325 int texturesurfaceindex;
10329 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10331 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10332 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)
10340 rsurface.lightmapcolor4f = rsurface.array_color4f;
10341 rsurface.lightmapcolor4f_bufferobject = 0;
10342 rsurface.lightmapcolor4f_bufferoffset = 0;
10345 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10347 int texturesurfaceindex;
10353 if (rsurface.lightmapcolor4f)
10355 // generate color arrays for the surfaces in this list
10356 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10358 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10359 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)
10361 f = RSurf_FogVertex(v);
10371 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10373 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10374 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)
10376 f = RSurf_FogVertex(v);
10384 rsurface.lightmapcolor4f = rsurface.array_color4f;
10385 rsurface.lightmapcolor4f_bufferobject = 0;
10386 rsurface.lightmapcolor4f_bufferoffset = 0;
10389 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10391 int texturesurfaceindex;
10397 if (!rsurface.lightmapcolor4f)
10399 // generate color arrays for the surfaces in this list
10400 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10402 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10403 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)
10405 f = RSurf_FogVertex(v);
10406 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10407 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10408 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10412 rsurface.lightmapcolor4f = rsurface.array_color4f;
10413 rsurface.lightmapcolor4f_bufferobject = 0;
10414 rsurface.lightmapcolor4f_bufferoffset = 0;
10417 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10419 int texturesurfaceindex;
10423 if (!rsurface.lightmapcolor4f)
10425 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10427 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10428 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)
10436 rsurface.lightmapcolor4f = rsurface.array_color4f;
10437 rsurface.lightmapcolor4f_bufferobject = 0;
10438 rsurface.lightmapcolor4f_bufferoffset = 0;
10441 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10443 int texturesurfaceindex;
10447 if (!rsurface.lightmapcolor4f)
10449 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10451 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10452 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)
10454 c2[0] = c[0] + r_refdef.scene.ambient;
10455 c2[1] = c[1] + r_refdef.scene.ambient;
10456 c2[2] = c[2] + r_refdef.scene.ambient;
10460 rsurface.lightmapcolor4f = rsurface.array_color4f;
10461 rsurface.lightmapcolor4f_bufferobject = 0;
10462 rsurface.lightmapcolor4f_bufferoffset = 0;
10465 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10468 rsurface.lightmapcolor4f = NULL;
10469 rsurface.lightmapcolor4f_bufferobject = 0;
10470 rsurface.lightmapcolor4f_bufferoffset = 0;
10471 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10472 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10473 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10474 GL_Color(r, g, b, a);
10475 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10478 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10480 // TODO: optimize applyfog && applycolor case
10481 // just apply fog if necessary, and tint the fog color array if necessary
10482 rsurface.lightmapcolor4f = NULL;
10483 rsurface.lightmapcolor4f_bufferobject = 0;
10484 rsurface.lightmapcolor4f_bufferoffset = 0;
10485 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10486 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10487 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10488 GL_Color(r, g, b, a);
10489 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10492 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10494 int texturesurfaceindex;
10498 if (texturesurfacelist[0]->lightmapinfo)
10500 // generate color arrays for the surfaces in this list
10501 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10503 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10504 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10506 if (surface->lightmapinfo->samples)
10508 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10509 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10510 VectorScale(lm, scale, c);
10511 if (surface->lightmapinfo->styles[1] != 255)
10513 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10515 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10516 VectorMA(c, scale, lm, c);
10517 if (surface->lightmapinfo->styles[2] != 255)
10520 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10521 VectorMA(c, scale, lm, c);
10522 if (surface->lightmapinfo->styles[3] != 255)
10525 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10526 VectorMA(c, scale, lm, c);
10536 rsurface.lightmapcolor4f = rsurface.array_color4f;
10537 rsurface.lightmapcolor4f_bufferobject = 0;
10538 rsurface.lightmapcolor4f_bufferoffset = 0;
10542 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10543 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10544 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10546 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10547 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10548 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10549 GL_Color(r, g, b, a);
10550 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10553 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10555 int texturesurfaceindex;
10562 vec3_t ambientcolor;
10563 vec3_t diffusecolor;
10567 VectorCopy(rsurface.modellight_lightdir, lightdir);
10568 f = 0.5f * r_refdef.lightmapintensity;
10569 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10570 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10571 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10572 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10573 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10574 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10576 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10578 // generate color arrays for the surfaces in this list
10579 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10581 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10582 int numverts = surface->num_vertices;
10583 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10584 n = rsurface.normal3f + 3 * surface->num_firstvertex;
10585 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10586 // q3-style directional shading
10587 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10589 if ((f = DotProduct(n, lightdir)) > 0)
10590 VectorMA(ambientcolor, f, diffusecolor, c);
10592 VectorCopy(ambientcolor, c);
10600 rsurface.lightmapcolor4f = rsurface.array_color4f;
10601 rsurface.lightmapcolor4f_bufferobject = 0;
10602 rsurface.lightmapcolor4f_bufferoffset = 0;
10603 *applycolor = false;
10607 *r = ambientcolor[0];
10608 *g = ambientcolor[1];
10609 *b = ambientcolor[2];
10610 rsurface.lightmapcolor4f = NULL;
10611 rsurface.lightmapcolor4f_bufferobject = 0;
10612 rsurface.lightmapcolor4f_bufferoffset = 0;
10616 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10618 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10619 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10620 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10621 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10622 GL_Color(r, g, b, a);
10623 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10626 void RSurf_SetupDepthAndCulling(void)
10628 // submodels are biased to avoid z-fighting with world surfaces that they
10629 // may be exactly overlapping (avoids z-fighting artifacts on certain
10630 // doors and things in Quake maps)
10631 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10632 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10633 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10634 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10637 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10639 // transparent sky would be ridiculous
10640 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10642 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10643 skyrenderlater = true;
10644 RSurf_SetupDepthAndCulling();
10645 GL_DepthMask(true);
10646 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10647 // skymasking on them, and Quake3 never did sky masking (unlike
10648 // software Quake and software Quake2), so disable the sky masking
10649 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10650 // and skymasking also looks very bad when noclipping outside the
10651 // level, so don't use it then either.
10652 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10654 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10655 R_Mesh_ColorPointer(NULL, 0, 0);
10656 R_Mesh_ResetTextureState();
10657 if (skyrendermasked)
10659 R_SetupShader_DepthOrShadow();
10660 // depth-only (masking)
10661 GL_ColorMask(0,0,0,0);
10662 // just to make sure that braindead drivers don't draw
10663 // anything despite that colormask...
10664 GL_BlendFunc(GL_ZERO, GL_ONE);
10668 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10670 GL_BlendFunc(GL_ONE, GL_ZERO);
10672 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10673 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10674 if (skyrendermasked)
10675 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10677 R_Mesh_ResetTextureState();
10678 GL_Color(1, 1, 1, 1);
10681 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10682 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10683 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10685 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10687 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10690 // render screenspace normalmap to texture
10691 GL_DepthMask(true);
10692 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10693 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10695 else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10697 // render water or distortion background, then blend surface on top
10698 GL_DepthMask(true);
10699 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10700 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10701 GL_DepthMask(false);
10702 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10703 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10704 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10706 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10710 // render surface normally
10711 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10712 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10713 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10714 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10715 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10716 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10718 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10722 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10724 // OpenGL 1.3 path - anything not completely ancient
10725 int texturesurfaceindex;
10726 qboolean applycolor;
10729 const texturelayer_t *layer;
10730 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10732 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10735 int layertexrgbscale;
10736 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10738 if (layerindex == 0)
10739 GL_AlphaTest(true);
10742 GL_AlphaTest(false);
10743 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10746 GL_DepthMask(layer->depthmask && writedepth);
10747 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10748 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10750 layertexrgbscale = 4;
10751 VectorScale(layer->color, 0.25f, layercolor);
10753 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10755 layertexrgbscale = 2;
10756 VectorScale(layer->color, 0.5f, layercolor);
10760 layertexrgbscale = 1;
10761 VectorScale(layer->color, 1.0f, layercolor);
10763 layercolor[3] = layer->color[3];
10764 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10765 R_Mesh_ColorPointer(NULL, 0, 0);
10766 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10767 switch (layer->type)
10769 case TEXTURELAYERTYPE_LITTEXTURE:
10770 // single-pass lightmapped texture with 2x rgbscale
10771 R_Mesh_TexBind(0, r_texture_white);
10772 R_Mesh_TexMatrix(0, NULL);
10773 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10774 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10775 R_Mesh_TexBind(1, layer->texture);
10776 R_Mesh_TexMatrix(1, &layer->texmatrix);
10777 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10778 R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10779 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10780 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10781 else if (rsurface.uselightmaptexture)
10782 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10784 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10786 case TEXTURELAYERTYPE_TEXTURE:
10787 // singletexture unlit texture with transparency support
10788 R_Mesh_TexBind(0, layer->texture);
10789 R_Mesh_TexMatrix(0, &layer->texmatrix);
10790 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10791 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10792 R_Mesh_TexBind(1, 0);
10793 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10794 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10796 case TEXTURELAYERTYPE_FOG:
10797 // singletexture fogging
10798 if (layer->texture)
10800 R_Mesh_TexBind(0, layer->texture);
10801 R_Mesh_TexMatrix(0, &layer->texmatrix);
10802 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10803 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10807 R_Mesh_TexBind(0, 0);
10808 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10810 R_Mesh_TexBind(1, 0);
10811 R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10812 // generate a color array for the fog pass
10813 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10814 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10820 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10821 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)
10823 f = 1 - RSurf_FogVertex(v);
10824 c[0] = layercolor[0];
10825 c[1] = layercolor[1];
10826 c[2] = layercolor[2];
10827 c[3] = f * layercolor[3];
10830 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10833 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10837 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10839 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10840 GL_AlphaTest(false);
10844 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10846 // OpenGL 1.1 - crusty old voodoo path
10847 int texturesurfaceindex;
10850 const texturelayer_t *layer;
10851 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10853 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10857 if (layerindex == 0)
10858 GL_AlphaTest(true);
10861 GL_AlphaTest(false);
10862 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10865 GL_DepthMask(layer->depthmask && writedepth);
10866 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10867 R_Mesh_ColorPointer(NULL, 0, 0);
10868 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10869 switch (layer->type)
10871 case TEXTURELAYERTYPE_LITTEXTURE:
10872 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10874 // two-pass lit texture with 2x rgbscale
10875 // first the lightmap pass
10876 R_Mesh_TexBind(0, r_texture_white);
10877 R_Mesh_TexMatrix(0, NULL);
10878 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10879 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10880 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10881 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10882 else if (rsurface.uselightmaptexture)
10883 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10885 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10886 // then apply the texture to it
10887 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10888 R_Mesh_TexBind(0, layer->texture);
10889 R_Mesh_TexMatrix(0, &layer->texmatrix);
10890 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10891 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10892 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);
10896 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10897 R_Mesh_TexBind(0, layer->texture);
10898 R_Mesh_TexMatrix(0, &layer->texmatrix);
10899 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10900 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10901 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10902 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);
10904 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);
10907 case TEXTURELAYERTYPE_TEXTURE:
10908 // singletexture unlit texture with transparency support
10909 R_Mesh_TexBind(0, layer->texture);
10910 R_Mesh_TexMatrix(0, &layer->texmatrix);
10911 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10912 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10913 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);
10915 case TEXTURELAYERTYPE_FOG:
10916 // singletexture fogging
10917 if (layer->texture)
10919 R_Mesh_TexBind(0, layer->texture);
10920 R_Mesh_TexMatrix(0, &layer->texmatrix);
10921 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10922 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10926 R_Mesh_TexBind(0, 0);
10927 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10929 // generate a color array for the fog pass
10930 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10931 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10937 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10938 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)
10940 f = 1 - RSurf_FogVertex(v);
10941 c[0] = layer->color[0];
10942 c[1] = layer->color[1];
10943 c[2] = layer->color[2];
10944 c[3] = f * layer->color[3];
10947 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10950 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10954 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10956 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10957 GL_AlphaTest(false);
10961 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10965 GL_AlphaTest(false);
10966 R_Mesh_ColorPointer(NULL, 0, 0);
10967 R_Mesh_ResetTextureState();
10968 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10970 if(rsurface.texture && rsurface.texture->currentskinframe)
10972 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10973 c[3] *= rsurface.texture->currentalpha;
10983 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10985 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10986 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10987 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10990 // brighten it up (as texture value 127 means "unlit")
10991 c[0] *= 2 * r_refdef.view.colorscale;
10992 c[1] *= 2 * r_refdef.view.colorscale;
10993 c[2] *= 2 * r_refdef.view.colorscale;
10995 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10996 c[3] *= r_wateralpha.value;
10998 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11000 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11001 GL_DepthMask(false);
11003 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11005 GL_BlendFunc(GL_ONE, GL_ONE);
11006 GL_DepthMask(false);
11008 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11010 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11011 GL_DepthMask(false);
11013 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11015 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11016 GL_DepthMask(false);
11020 GL_BlendFunc(GL_ONE, GL_ZERO);
11021 GL_DepthMask(writedepth);
11024 rsurface.lightmapcolor4f = NULL;
11026 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11028 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11030 rsurface.lightmapcolor4f = NULL;
11031 rsurface.lightmapcolor4f_bufferobject = 0;
11032 rsurface.lightmapcolor4f_bufferoffset = 0;
11034 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11036 qboolean applycolor = true;
11039 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11041 r_refdef.lightmapintensity = 1;
11042 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11043 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11047 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11049 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11050 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11051 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11054 if(!rsurface.lightmapcolor4f)
11055 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11057 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11058 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11059 if(r_refdef.fogenabled)
11060 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11062 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11063 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11066 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11069 RSurf_SetupDepthAndCulling();
11070 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11072 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11075 switch (vid.renderpath)
11077 case RENDERPATH_GL20:
11078 case RENDERPATH_CGGL:
11079 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11081 case RENDERPATH_GL13:
11082 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11084 case RENDERPATH_GL11:
11085 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11091 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11094 RSurf_SetupDepthAndCulling();
11095 if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11097 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11100 switch (vid.renderpath)
11102 case RENDERPATH_GL20:
11103 case RENDERPATH_CGGL:
11104 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11106 case RENDERPATH_GL13:
11107 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11109 case RENDERPATH_GL11:
11110 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11116 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11119 int texturenumsurfaces, endsurface;
11120 texture_t *texture;
11121 const msurface_t *surface;
11122 const msurface_t *texturesurfacelist[256];
11124 // if the model is static it doesn't matter what value we give for
11125 // wantnormals and wanttangents, so this logic uses only rules applicable
11126 // to a model, knowing that they are meaningless otherwise
11127 if (ent == r_refdef.scene.worldentity)
11128 RSurf_ActiveWorldEntity();
11129 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11130 RSurf_ActiveModelEntity(ent, false, false, false);
11133 switch (vid.renderpath)
11135 case RENDERPATH_GL20:
11136 case RENDERPATH_CGGL:
11137 RSurf_ActiveModelEntity(ent, true, true, false);
11139 case RENDERPATH_GL13:
11140 case RENDERPATH_GL11:
11141 RSurf_ActiveModelEntity(ent, true, false, false);
11146 if (r_transparentdepthmasking.integer)
11148 qboolean setup = false;
11149 for (i = 0;i < numsurfaces;i = j)
11152 surface = rsurface.modelsurfaces + surfacelist[i];
11153 texture = surface->texture;
11154 rsurface.texture = R_GetCurrentTexture(texture);
11155 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11156 // scan ahead until we find a different texture
11157 endsurface = min(i + 1024, numsurfaces);
11158 texturenumsurfaces = 0;
11159 texturesurfacelist[texturenumsurfaces++] = surface;
11160 for (;j < endsurface;j++)
11162 surface = rsurface.modelsurfaces + surfacelist[j];
11163 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11165 texturesurfacelist[texturenumsurfaces++] = surface;
11167 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11169 // render the range of surfaces as depth
11173 GL_ColorMask(0,0,0,0);
11175 GL_DepthTest(true);
11176 GL_BlendFunc(GL_ONE, GL_ZERO);
11177 GL_DepthMask(true);
11178 GL_AlphaTest(false);
11179 R_Mesh_ColorPointer(NULL, 0, 0);
11180 R_Mesh_ResetTextureState();
11181 R_SetupShader_DepthOrShadow();
11183 RSurf_SetupDepthAndCulling();
11184 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11185 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11188 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11191 for (i = 0;i < numsurfaces;i = j)
11194 surface = rsurface.modelsurfaces + surfacelist[i];
11195 texture = surface->texture;
11196 rsurface.texture = R_GetCurrentTexture(texture);
11197 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11198 // scan ahead until we find a different texture
11199 endsurface = min(i + 1024, numsurfaces);
11200 texturenumsurfaces = 0;
11201 texturesurfacelist[texturenumsurfaces++] = surface;
11202 for (;j < endsurface;j++)
11204 surface = rsurface.modelsurfaces + surfacelist[j];
11205 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11207 texturesurfacelist[texturenumsurfaces++] = surface;
11209 // render the range of surfaces
11210 if (ent == r_refdef.scene.worldentity)
11211 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11213 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11215 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11216 GL_AlphaTest(false);
11219 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11221 // transparent surfaces get pushed off into the transparent queue
11222 int surfacelistindex;
11223 const msurface_t *surface;
11224 vec3_t tempcenter, center;
11225 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11227 surface = texturesurfacelist[surfacelistindex];
11228 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11229 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11230 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11231 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11232 if (queueentity->transparent_offset) // transparent offset
11234 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11235 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11236 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11238 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11242 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11244 const entity_render_t *queueentity = r_refdef.scene.worldentity;
11248 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11250 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11252 RSurf_SetupDepthAndCulling();
11253 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11254 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11258 if (!rsurface.texture->currentnumlayers)
11260 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11261 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11263 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11265 else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11267 RSurf_SetupDepthAndCulling();
11268 GL_AlphaTest(false);
11269 R_Mesh_ColorPointer(NULL, 0, 0);
11270 R_Mesh_ResetTextureState();
11271 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11272 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11273 GL_DepthMask(true);
11274 GL_BlendFunc(GL_ONE, GL_ZERO);
11275 GL_Color(0, 0, 0, 1);
11276 GL_DepthTest(writedepth);
11277 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11279 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11281 RSurf_SetupDepthAndCulling();
11282 GL_AlphaTest(false);
11283 R_Mesh_ColorPointer(NULL, 0, 0);
11284 R_Mesh_ResetTextureState();
11285 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11286 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11287 GL_DepthMask(true);
11288 GL_BlendFunc(GL_ONE, GL_ZERO);
11289 GL_DepthTest(true);
11290 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11292 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11293 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11294 else if (!rsurface.texture->currentnumlayers)
11296 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11298 // in the deferred case, transparent surfaces were queued during prepass
11299 if (!r_shadow_usingdeferredprepass)
11300 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11304 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11305 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11310 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11313 texture_t *texture;
11314 // break the surface list down into batches by texture and use of lightmapping
11315 for (i = 0;i < numsurfaces;i = j)
11318 // texture is the base texture pointer, rsurface.texture is the
11319 // current frame/skin the texture is directing us to use (for example
11320 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11321 // use skin 1 instead)
11322 texture = surfacelist[i]->texture;
11323 rsurface.texture = R_GetCurrentTexture(texture);
11324 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11325 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11327 // if this texture is not the kind we want, skip ahead to the next one
11328 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11332 // simply scan ahead until we find a different texture or lightmap state
11333 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11335 // render the range of surfaces
11336 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11340 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11345 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11347 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11349 RSurf_SetupDepthAndCulling();
11350 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11351 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11355 if (!rsurface.texture->currentnumlayers)
11357 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11358 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11360 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11362 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11364 RSurf_SetupDepthAndCulling();
11365 GL_AlphaTest(false);
11366 R_Mesh_ColorPointer(NULL, 0, 0);
11367 R_Mesh_ResetTextureState();
11368 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11369 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11370 GL_DepthMask(true);
11371 GL_BlendFunc(GL_ONE, GL_ZERO);
11372 GL_Color(0, 0, 0, 1);
11373 GL_DepthTest(writedepth);
11374 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11376 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11378 RSurf_SetupDepthAndCulling();
11379 GL_AlphaTest(false);
11380 R_Mesh_ColorPointer(NULL, 0, 0);
11381 R_Mesh_ResetTextureState();
11382 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11383 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11384 GL_DepthMask(true);
11385 GL_BlendFunc(GL_ONE, GL_ZERO);
11386 GL_DepthTest(true);
11387 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11389 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11390 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11391 else if (!rsurface.texture->currentnumlayers)
11393 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11395 // in the deferred case, transparent surfaces were queued during prepass
11396 if (!r_shadow_usingdeferredprepass)
11397 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11401 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11402 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11407 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11410 texture_t *texture;
11411 // break the surface list down into batches by texture and use of lightmapping
11412 for (i = 0;i < numsurfaces;i = j)
11415 // texture is the base texture pointer, rsurface.texture is the
11416 // current frame/skin the texture is directing us to use (for example
11417 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11418 // use skin 1 instead)
11419 texture = surfacelist[i]->texture;
11420 rsurface.texture = R_GetCurrentTexture(texture);
11421 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11422 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11424 // if this texture is not the kind we want, skip ahead to the next one
11425 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11429 // simply scan ahead until we find a different texture or lightmap state
11430 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11432 // render the range of surfaces
11433 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11437 float locboxvertex3f[6*4*3] =
11439 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11440 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11441 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11442 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11443 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11444 1,0,0, 0,0,0, 0,1,0, 1,1,0
11447 unsigned short locboxelements[6*2*3] =
11452 12,13,14, 12,14,15,
11453 16,17,18, 16,18,19,
11457 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11460 cl_locnode_t *loc = (cl_locnode_t *)ent;
11462 float vertex3f[6*4*3];
11464 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11465 GL_DepthMask(false);
11466 GL_DepthRange(0, 1);
11467 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11468 GL_DepthTest(true);
11469 GL_CullFace(GL_NONE);
11470 R_EntityMatrix(&identitymatrix);
11472 R_Mesh_VertexPointer(vertex3f, 0, 0);
11473 R_Mesh_ColorPointer(NULL, 0, 0);
11474 R_Mesh_ResetTextureState();
11475 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11477 i = surfacelist[0];
11478 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11479 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11480 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11481 surfacelist[0] < 0 ? 0.5f : 0.125f);
11483 if (VectorCompare(loc->mins, loc->maxs))
11485 VectorSet(size, 2, 2, 2);
11486 VectorMA(loc->mins, -0.5f, size, mins);
11490 VectorCopy(loc->mins, mins);
11491 VectorSubtract(loc->maxs, loc->mins, size);
11494 for (i = 0;i < 6*4*3;)
11495 for (j = 0;j < 3;j++, i++)
11496 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11498 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11501 void R_DrawLocs(void)
11504 cl_locnode_t *loc, *nearestloc;
11506 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11507 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11509 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11510 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11514 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11516 if (decalsystem->decals)
11517 Mem_Free(decalsystem->decals);
11518 memset(decalsystem, 0, sizeof(*decalsystem));
11521 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)
11524 tridecal_t *decals;
11527 // expand or initialize the system
11528 if (decalsystem->maxdecals <= decalsystem->numdecals)
11530 decalsystem_t old = *decalsystem;
11531 qboolean useshortelements;
11532 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11533 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11534 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)));
11535 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11536 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11537 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11538 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11539 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11540 if (decalsystem->numdecals)
11541 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11543 Mem_Free(old.decals);
11544 for (i = 0;i < decalsystem->maxdecals*3;i++)
11545 decalsystem->element3i[i] = i;
11546 if (useshortelements)
11547 for (i = 0;i < decalsystem->maxdecals*3;i++)
11548 decalsystem->element3s[i] = i;
11551 // grab a decal and search for another free slot for the next one
11552 decals = decalsystem->decals;
11553 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11554 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11556 decalsystem->freedecal = i;
11557 if (decalsystem->numdecals <= i)
11558 decalsystem->numdecals = i + 1;
11560 // initialize the decal
11562 decal->triangleindex = triangleindex;
11563 decal->surfaceindex = surfaceindex;
11564 decal->decalsequence = decalsequence;
11565 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11566 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11567 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11568 decal->color4ub[0][3] = 255;
11569 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11570 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11571 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11572 decal->color4ub[1][3] = 255;
11573 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11574 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11575 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11576 decal->color4ub[2][3] = 255;
11577 decal->vertex3f[0][0] = v0[0];
11578 decal->vertex3f[0][1] = v0[1];
11579 decal->vertex3f[0][2] = v0[2];
11580 decal->vertex3f[1][0] = v1[0];
11581 decal->vertex3f[1][1] = v1[1];
11582 decal->vertex3f[1][2] = v1[2];
11583 decal->vertex3f[2][0] = v2[0];
11584 decal->vertex3f[2][1] = v2[1];
11585 decal->vertex3f[2][2] = v2[2];
11586 decal->texcoord2f[0][0] = t0[0];
11587 decal->texcoord2f[0][1] = t0[1];
11588 decal->texcoord2f[1][0] = t1[0];
11589 decal->texcoord2f[1][1] = t1[1];
11590 decal->texcoord2f[2][0] = t2[0];
11591 decal->texcoord2f[2][1] = t2[1];
11594 extern cvar_t cl_decals_bias;
11595 extern cvar_t cl_decals_models;
11596 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11597 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)
11599 matrix4x4_t projection;
11600 decalsystem_t *decalsystem;
11603 const float *vertex3f;
11604 const msurface_t *surface;
11605 const msurface_t *surfaces;
11606 const int *surfacelist;
11607 const texture_t *texture;
11609 int numsurfacelist;
11610 int surfacelistindex;
11617 float localorigin[3];
11618 float localnormal[3];
11619 float localmins[3];
11620 float localmaxs[3];
11626 float planes[6][4];
11628 float points[2][9][3];
11632 decalsystem = &ent->decalsystem;
11633 model = ent->model;
11634 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11636 R_DecalSystem_Reset(&ent->decalsystem);
11640 if (!model->brush.data_nodes && !cl_decals_models.integer)
11642 if (decalsystem->model)
11643 R_DecalSystem_Reset(decalsystem);
11647 if (decalsystem->model != model)
11648 R_DecalSystem_Reset(decalsystem);
11649 decalsystem->model = model;
11651 RSurf_ActiveModelEntity(ent, false, false, false);
11653 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11654 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11655 VectorNormalize(localnormal);
11656 localsize = worldsize*rsurface.inversematrixscale;
11657 localmins[0] = localorigin[0] - localsize;
11658 localmins[1] = localorigin[1] - localsize;
11659 localmins[2] = localorigin[2] - localsize;
11660 localmaxs[0] = localorigin[0] + localsize;
11661 localmaxs[1] = localorigin[1] + localsize;
11662 localmaxs[2] = localorigin[2] + localsize;
11664 //VectorCopy(localnormal, planes[4]);
11665 //VectorVectors(planes[4], planes[2], planes[0]);
11666 AnglesFromVectors(angles, localnormal, NULL, false);
11667 AngleVectors(angles, planes[0], planes[2], planes[4]);
11668 VectorNegate(planes[0], planes[1]);
11669 VectorNegate(planes[2], planes[3]);
11670 VectorNegate(planes[4], planes[5]);
11671 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11672 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11673 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11674 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11675 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11676 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11681 matrix4x4_t forwardprojection;
11682 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11683 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11688 float projectionvector[4][3];
11689 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11690 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11691 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11692 projectionvector[0][0] = planes[0][0] * ilocalsize;
11693 projectionvector[0][1] = planes[1][0] * ilocalsize;
11694 projectionvector[0][2] = planes[2][0] * ilocalsize;
11695 projectionvector[1][0] = planes[0][1] * ilocalsize;
11696 projectionvector[1][1] = planes[1][1] * ilocalsize;
11697 projectionvector[1][2] = planes[2][1] * ilocalsize;
11698 projectionvector[2][0] = planes[0][2] * ilocalsize;
11699 projectionvector[2][1] = planes[1][2] * ilocalsize;
11700 projectionvector[2][2] = planes[2][2] * ilocalsize;
11701 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11702 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11703 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11704 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11708 dynamic = model->surfmesh.isanimated;
11709 vertex3f = rsurface.modelvertex3f;
11710 numsurfacelist = model->nummodelsurfaces;
11711 surfacelist = model->sortedmodelsurfaces;
11712 surfaces = model->data_surfaces;
11713 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11715 surfaceindex = surfacelist[surfacelistindex];
11716 surface = surfaces + surfaceindex;
11717 // check cull box first because it rejects more than any other check
11718 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11720 // skip transparent surfaces
11721 texture = surface->texture;
11722 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11724 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11726 numtriangles = surface->num_triangles;
11727 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11729 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11731 index = 3*e[cornerindex];
11732 VectorCopy(vertex3f + index, v[cornerindex]);
11735 //TriangleNormal(v[0], v[1], v[2], normal);
11736 //if (DotProduct(normal, localnormal) < 0.0f)
11738 // clip by each of the box planes formed from the projection matrix
11739 // if anything survives, we emit the decal
11740 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]);
11743 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]);
11746 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]);
11749 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]);
11752 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]);
11755 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]);
11758 // some part of the triangle survived, so we have to accept it...
11761 // dynamic always uses the original triangle
11763 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11765 index = 3*e[cornerindex];
11766 VectorCopy(vertex3f + index, v[cornerindex]);
11769 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11771 // convert vertex positions to texcoords
11772 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11773 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11774 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11775 // calculate distance fade from the projection origin
11776 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11777 f = bound(0.0f, f, 1.0f);
11778 c[cornerindex][0] = r * f;
11779 c[cornerindex][1] = g * f;
11780 c[cornerindex][2] = b * f;
11781 c[cornerindex][3] = 1.0f;
11782 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11785 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);
11787 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11788 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);
11793 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11794 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)
11796 int renderentityindex;
11797 float worldmins[3];
11798 float worldmaxs[3];
11799 entity_render_t *ent;
11801 if (!cl_decals_newsystem.integer)
11804 worldmins[0] = worldorigin[0] - worldsize;
11805 worldmins[1] = worldorigin[1] - worldsize;
11806 worldmins[2] = worldorigin[2] - worldsize;
11807 worldmaxs[0] = worldorigin[0] + worldsize;
11808 worldmaxs[1] = worldorigin[1] + worldsize;
11809 worldmaxs[2] = worldorigin[2] + worldsize;
11811 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11813 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11815 ent = r_refdef.scene.entities[renderentityindex];
11816 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11819 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11823 typedef struct r_decalsystem_splatqueue_s
11825 vec3_t worldorigin;
11826 vec3_t worldnormal;
11832 r_decalsystem_splatqueue_t;
11834 int r_decalsystem_numqueued = 0;
11835 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11837 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)
11839 r_decalsystem_splatqueue_t *queue;
11841 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11844 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11845 VectorCopy(worldorigin, queue->worldorigin);
11846 VectorCopy(worldnormal, queue->worldnormal);
11847 Vector4Set(queue->color, r, g, b, a);
11848 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11849 queue->worldsize = worldsize;
11850 queue->decalsequence = cl.decalsequence++;
11853 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11856 r_decalsystem_splatqueue_t *queue;
11858 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11859 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);
11860 r_decalsystem_numqueued = 0;
11863 extern cvar_t cl_decals_max;
11864 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11867 decalsystem_t *decalsystem = &ent->decalsystem;
11874 if (!decalsystem->numdecals)
11877 if (r_showsurfaces.integer)
11880 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11882 R_DecalSystem_Reset(decalsystem);
11886 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11887 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11889 if (decalsystem->lastupdatetime)
11890 frametime = (cl.time - decalsystem->lastupdatetime);
11893 decalsystem->lastupdatetime = cl.time;
11894 decal = decalsystem->decals;
11895 numdecals = decalsystem->numdecals;
11897 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11899 if (decal->color4ub[0][3])
11901 decal->lived += frametime;
11902 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11904 memset(decal, 0, sizeof(*decal));
11905 if (decalsystem->freedecal > i)
11906 decalsystem->freedecal = i;
11910 decal = decalsystem->decals;
11911 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11914 // collapse the array by shuffling the tail decals into the gaps
11917 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11918 decalsystem->freedecal++;
11919 if (decalsystem->freedecal == numdecals)
11921 decal[decalsystem->freedecal] = decal[--numdecals];
11924 decalsystem->numdecals = numdecals;
11926 if (numdecals <= 0)
11928 // if there are no decals left, reset decalsystem
11929 R_DecalSystem_Reset(decalsystem);
11933 extern skinframe_t *decalskinframe;
11934 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11937 decalsystem_t *decalsystem = &ent->decalsystem;
11946 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11949 numdecals = decalsystem->numdecals;
11953 if (r_showsurfaces.integer)
11956 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11958 R_DecalSystem_Reset(decalsystem);
11962 // if the model is static it doesn't matter what value we give for
11963 // wantnormals and wanttangents, so this logic uses only rules applicable
11964 // to a model, knowing that they are meaningless otherwise
11965 if (ent == r_refdef.scene.worldentity)
11966 RSurf_ActiveWorldEntity();
11968 RSurf_ActiveModelEntity(ent, false, false, false);
11970 decalsystem->lastupdatetime = cl.time;
11971 decal = decalsystem->decals;
11973 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11975 // update vertex positions for animated models
11976 v3f = decalsystem->vertex3f;
11977 c4f = decalsystem->color4f;
11978 t2f = decalsystem->texcoord2f;
11979 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11981 if (!decal->color4ub[0][3])
11984 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11987 // update color values for fading decals
11988 if (decal->lived >= cl_decals_time.value)
11990 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11991 alpha *= (1.0f/255.0f);
11994 alpha = 1.0f/255.0f;
11996 c4f[ 0] = decal->color4ub[0][0] * alpha;
11997 c4f[ 1] = decal->color4ub[0][1] * alpha;
11998 c4f[ 2] = decal->color4ub[0][2] * alpha;
12000 c4f[ 4] = decal->color4ub[1][0] * alpha;
12001 c4f[ 5] = decal->color4ub[1][1] * alpha;
12002 c4f[ 6] = decal->color4ub[1][2] * alpha;
12004 c4f[ 8] = decal->color4ub[2][0] * alpha;
12005 c4f[ 9] = decal->color4ub[2][1] * alpha;
12006 c4f[10] = decal->color4ub[2][2] * alpha;
12009 t2f[0] = decal->texcoord2f[0][0];
12010 t2f[1] = decal->texcoord2f[0][1];
12011 t2f[2] = decal->texcoord2f[1][0];
12012 t2f[3] = decal->texcoord2f[1][1];
12013 t2f[4] = decal->texcoord2f[2][0];
12014 t2f[5] = decal->texcoord2f[2][1];
12016 // update vertex positions for animated models
12017 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12019 e = rsurface.modelelement3i + 3*decal->triangleindex;
12020 VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12021 VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12022 VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12026 VectorCopy(decal->vertex3f[0], v3f);
12027 VectorCopy(decal->vertex3f[1], v3f + 3);
12028 VectorCopy(decal->vertex3f[2], v3f + 6);
12039 r_refdef.stats.drawndecals += numtris;
12041 if (r_refdef.fogenabled)
12043 switch(vid.renderpath)
12045 case RENDERPATH_GL20:
12046 case RENDERPATH_CGGL:
12047 case RENDERPATH_GL13:
12048 case RENDERPATH_GL11:
12049 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
12051 alpha = RSurf_FogVertex(v3f);
12060 // now render the decals all at once
12061 // (this assumes they all use one particle font texture!)
12062 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);
12063 R_Mesh_ResetTextureState();
12064 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12065 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12066 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12067 GL_DepthMask(false);
12068 GL_DepthRange(0, 1);
12069 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12070 GL_DepthTest(true);
12071 GL_CullFace(GL_NONE);
12072 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12073 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12074 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12078 static void R_DrawModelDecals(void)
12082 // fade faster when there are too many decals
12083 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12084 for (i = 0;i < r_refdef.scene.numentities;i++)
12085 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12087 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12088 for (i = 0;i < r_refdef.scene.numentities;i++)
12089 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12090 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12092 R_DecalSystem_ApplySplatEntitiesQueue();
12094 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12095 for (i = 0;i < r_refdef.scene.numentities;i++)
12096 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12098 r_refdef.stats.totaldecals += numdecals;
12100 if (r_showsurfaces.integer)
12103 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12105 for (i = 0;i < r_refdef.scene.numentities;i++)
12107 if (!r_refdef.viewcache.entityvisible[i])
12109 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12110 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12114 void R_DrawDebugModel(void)
12116 entity_render_t *ent = rsurface.entity;
12117 int i, j, k, l, flagsmask;
12119 const msurface_t *surface;
12120 dp_model_t *model = ent->model;
12123 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12125 R_Mesh_ColorPointer(NULL, 0, 0);
12126 R_Mesh_ResetTextureState();
12127 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12128 GL_DepthRange(0, 1);
12129 GL_DepthTest(!r_showdisabledepthtest.integer);
12130 GL_DepthMask(false);
12131 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12133 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12135 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12136 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12138 if (brush->colbrushf && brush->colbrushf->numtriangles)
12140 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12141 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);
12142 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12145 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12147 if (surface->num_collisiontriangles)
12149 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12150 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);
12151 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12156 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12158 if (r_showtris.integer || r_shownormals.integer)
12160 if (r_showdisabledepthtest.integer)
12162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12163 GL_DepthMask(false);
12167 GL_BlendFunc(GL_ONE, GL_ZERO);
12168 GL_DepthMask(true);
12170 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12172 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12174 rsurface.texture = R_GetCurrentTexture(surface->texture);
12175 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12177 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12178 if (r_showtris.value > 0)
12180 if (!rsurface.texture->currentlayers->depthmask)
12181 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12182 else if (ent == r_refdef.scene.worldentity)
12183 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12185 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12186 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12187 R_Mesh_ColorPointer(NULL, 0, 0);
12188 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12189 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12190 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12191 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);
12192 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12195 if (r_shownormals.value < 0)
12197 qglBegin(GL_LINES);
12198 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12200 VectorCopy(rsurface.vertex3f + l * 3, v);
12201 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12202 qglVertex3f(v[0], v[1], v[2]);
12203 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12204 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12205 qglVertex3f(v[0], v[1], v[2]);
12210 if (r_shownormals.value > 0)
12212 qglBegin(GL_LINES);
12213 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12215 VectorCopy(rsurface.vertex3f + l * 3, v);
12216 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12217 qglVertex3f(v[0], v[1], v[2]);
12218 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12219 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12220 qglVertex3f(v[0], v[1], v[2]);
12224 qglBegin(GL_LINES);
12225 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12227 VectorCopy(rsurface.vertex3f + l * 3, v);
12228 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12229 qglVertex3f(v[0], v[1], v[2]);
12230 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12231 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12232 qglVertex3f(v[0], v[1], v[2]);
12236 qglBegin(GL_LINES);
12237 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12239 VectorCopy(rsurface.vertex3f + l * 3, v);
12240 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12241 qglVertex3f(v[0], v[1], v[2]);
12242 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12243 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12244 qglVertex3f(v[0], v[1], v[2]);
12251 rsurface.texture = NULL;
12255 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12256 int r_maxsurfacelist = 0;
12257 const msurface_t **r_surfacelist = NULL;
12258 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12260 int i, j, endj, flagsmask;
12261 dp_model_t *model = r_refdef.scene.worldmodel;
12262 msurface_t *surfaces;
12263 unsigned char *update;
12264 int numsurfacelist = 0;
12268 if (r_maxsurfacelist < model->num_surfaces)
12270 r_maxsurfacelist = model->num_surfaces;
12272 Mem_Free((msurface_t**)r_surfacelist);
12273 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12276 RSurf_ActiveWorldEntity();
12278 surfaces = model->data_surfaces;
12279 update = model->brushq1.lightmapupdateflags;
12281 // update light styles on this submodel
12282 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12284 model_brush_lightstyleinfo_t *style;
12285 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12287 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12289 int *list = style->surfacelist;
12290 style->value = r_refdef.scene.lightstylevalue[style->style];
12291 for (j = 0;j < style->numsurfaces;j++)
12292 update[list[j]] = true;
12297 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12301 R_DrawDebugModel();
12302 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12306 rsurface.uselightmaptexture = false;
12307 rsurface.texture = NULL;
12308 rsurface.rtlight = NULL;
12309 numsurfacelist = 0;
12310 // add visible surfaces to draw list
12311 for (i = 0;i < model->nummodelsurfaces;i++)
12313 j = model->sortedmodelsurfaces[i];
12314 if (r_refdef.viewcache.world_surfacevisible[j])
12315 r_surfacelist[numsurfacelist++] = surfaces + j;
12317 // update lightmaps if needed
12318 if (model->brushq1.firstrender)
12320 model->brushq1.firstrender = false;
12321 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12323 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12327 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12328 if (r_refdef.viewcache.world_surfacevisible[j])
12330 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12332 // don't do anything if there were no surfaces
12333 if (!numsurfacelist)
12335 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12338 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12339 GL_AlphaTest(false);
12341 // add to stats if desired
12342 if (r_speeds.integer && !skysurfaces && !depthonly)
12344 r_refdef.stats.world_surfaces += numsurfacelist;
12345 for (j = 0;j < numsurfacelist;j++)
12346 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12349 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12352 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12354 int i, j, endj, flagsmask;
12355 dp_model_t *model = ent->model;
12356 msurface_t *surfaces;
12357 unsigned char *update;
12358 int numsurfacelist = 0;
12362 if (r_maxsurfacelist < model->num_surfaces)
12364 r_maxsurfacelist = model->num_surfaces;
12366 Mem_Free((msurface_t **)r_surfacelist);
12367 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12370 // if the model is static it doesn't matter what value we give for
12371 // wantnormals and wanttangents, so this logic uses only rules applicable
12372 // to a model, knowing that they are meaningless otherwise
12373 if (ent == r_refdef.scene.worldentity)
12374 RSurf_ActiveWorldEntity();
12375 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12376 RSurf_ActiveModelEntity(ent, false, false, false);
12378 RSurf_ActiveModelEntity(ent, true, true, true);
12379 else if (depthonly)
12381 switch (vid.renderpath)
12383 case RENDERPATH_GL20:
12384 case RENDERPATH_CGGL:
12385 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12387 case RENDERPATH_GL13:
12388 case RENDERPATH_GL11:
12389 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12395 switch (vid.renderpath)
12397 case RENDERPATH_GL20:
12398 case RENDERPATH_CGGL:
12399 RSurf_ActiveModelEntity(ent, true, true, false);
12401 case RENDERPATH_GL13:
12402 case RENDERPATH_GL11:
12403 RSurf_ActiveModelEntity(ent, true, false, false);
12408 surfaces = model->data_surfaces;
12409 update = model->brushq1.lightmapupdateflags;
12411 // update light styles
12412 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12414 model_brush_lightstyleinfo_t *style;
12415 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12417 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12419 int *list = style->surfacelist;
12420 style->value = r_refdef.scene.lightstylevalue[style->style];
12421 for (j = 0;j < style->numsurfaces;j++)
12422 update[list[j]] = true;
12427 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12431 R_DrawDebugModel();
12432 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12436 rsurface.uselightmaptexture = false;
12437 rsurface.texture = NULL;
12438 rsurface.rtlight = NULL;
12439 numsurfacelist = 0;
12440 // add visible surfaces to draw list
12441 for (i = 0;i < model->nummodelsurfaces;i++)
12442 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12443 // don't do anything if there were no surfaces
12444 if (!numsurfacelist)
12446 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12449 // update lightmaps if needed
12453 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12458 R_BuildLightMap(ent, surfaces + j);
12463 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12465 R_BuildLightMap(ent, surfaces + j);
12466 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12467 GL_AlphaTest(false);
12469 // add to stats if desired
12470 if (r_speeds.integer && !skysurfaces && !depthonly)
12472 r_refdef.stats.entities_surfaces += numsurfacelist;
12473 for (j = 0;j < numsurfacelist;j++)
12474 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12477 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12480 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12482 static texture_t texture;
12483 static msurface_t surface;
12484 const msurface_t *surfacelist = &surface;
12486 // fake enough texture and surface state to render this geometry
12488 texture.update_lastrenderframe = -1; // regenerate this texture
12489 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12490 texture.currentskinframe = skinframe;
12491 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12492 texture.specularscalemod = 1;
12493 texture.specularpowermod = 1;
12495 surface.texture = &texture;
12496 surface.num_triangles = numtriangles;
12497 surface.num_firsttriangle = firsttriangle;
12498 surface.num_vertices = numvertices;
12499 surface.num_firstvertex = firstvertex;
12502 rsurface.texture = R_GetCurrentTexture(surface.texture);
12503 rsurface.uselightmaptexture = false;
12504 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12507 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)
12509 static msurface_t surface;
12510 const msurface_t *surfacelist = &surface;
12512 // fake enough texture and surface state to render this geometry
12514 surface.texture = texture;
12515 surface.num_triangles = numtriangles;
12516 surface.num_firsttriangle = firsttriangle;
12517 surface.num_vertices = numvertices;
12518 surface.num_firstvertex = firstvertex;
12521 rsurface.texture = R_GetCurrentTexture(surface.texture);
12522 rsurface.uselightmaptexture = false;
12523 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);