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"
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 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)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 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"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 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)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67 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"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
73 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)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 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"};
77 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"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 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"};
80 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"};
81 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"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 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)"};
90 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)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 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."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 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."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 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"};
108 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"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 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"};
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
124 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)"};
125 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"};
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
137 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)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 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)"};
143 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)"};
144 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)"};
145 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)"};
147 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)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 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"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 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)"};
171 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"};
173 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"};
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 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"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 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)"};
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
187 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)"};
189 extern cvar_t v_glslgamma;
191 extern qboolean v_flipped_state;
193 static struct r_bloomstate_s
198 int bloomwidth, bloomheight;
200 int screentexturewidth, screentextureheight;
201 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
203 int bloomtexturewidth, bloomtextureheight;
204 rtexture_t *texture_bloom;
206 // arrays for rendering the screen passes
207 float screentexcoord2f[8];
208 float bloomtexcoord2f[8];
209 float offsettexcoord2f[8];
211 r_viewport_t viewport;
215 r_waterstate_t r_waterstate;
217 /// shadow volume bsp struct with automatically growing nodes buffer
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
249 typedef struct r_qwskincache_s
251 char name[MAX_QPATH];
252 skinframe_t *skinframe;
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
269 const float r_d3dscreenvertex3f[12] =
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
280 for (i = 0;i < verts;i++)
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
294 for (i = 0;i < verts;i++)
304 // FIXME: move this to client?
307 if (gamemode == GAME_NEHAHRA)
309 Cvar_Set("gl_fogenable", "0");
310 Cvar_Set("gl_fogdensity", "0.2");
311 Cvar_Set("gl_fogred", "0.3");
312 Cvar_Set("gl_foggreen", "0.3");
313 Cvar_Set("gl_fogblue", "0.3");
315 r_refdef.fog_density = 0;
316 r_refdef.fog_red = 0;
317 r_refdef.fog_green = 0;
318 r_refdef.fog_blue = 0;
319 r_refdef.fog_alpha = 1;
320 r_refdef.fog_start = 0;
321 r_refdef.fog_end = 16384;
322 r_refdef.fog_height = 1<<30;
323 r_refdef.fog_fadedepth = 128;
324 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
327 static void R_BuildBlankTextures(void)
329 unsigned char data[4];
330 data[2] = 128; // normal X
331 data[1] = 128; // normal Y
332 data[0] = 255; // normal Z
333 data[3] = 128; // height
334 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
339 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
344 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
349 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352 static void R_BuildNoTexture(void)
355 unsigned char pix[16][16][4];
356 // this makes a light grey/dark grey checkerboard texture
357 for (y = 0;y < 16;y++)
359 for (x = 0;x < 16;x++)
361 if ((y < 8) ^ (x < 8))
377 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
380 static void R_BuildWhiteCube(void)
382 unsigned char data[6*1*1*4];
383 memset(data, 255, sizeof(data));
384 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNormalizationCube(void)
391 vec_t s, t, intensity;
394 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395 for (side = 0;side < 6;side++)
397 for (y = 0;y < NORMSIZE;y++)
399 for (x = 0;x < NORMSIZE;x++)
401 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 intensity = 127.0f / sqrt(DotProduct(v, v));
438 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441 data[((side*64+y)*64+x)*4+3] = 255;
445 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
449 static void R_BuildFogTexture(void)
453 unsigned char data1[FOGWIDTH][4];
454 //unsigned char data2[FOGWIDTH][4];
457 r_refdef.fogmasktable_start = r_refdef.fog_start;
458 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459 r_refdef.fogmasktable_range = r_refdef.fogrange;
460 r_refdef.fogmasktable_density = r_refdef.fog_density;
462 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
465 d = (x * r - r_refdef.fogmasktable_start);
466 if(developer_extra.integer)
467 Con_DPrintf("%f ", d);
469 if (r_fog_exp2.integer)
470 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
472 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473 if(developer_extra.integer)
474 Con_DPrintf(" : %f ", alpha);
475 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476 if(developer_extra.integer)
477 Con_DPrintf(" = %f\n", alpha);
478 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
481 for (x = 0;x < FOGWIDTH;x++)
483 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
488 //data2[x][0] = 255 - b;
489 //data2[x][1] = 255 - b;
490 //data2[x][2] = 255 - b;
493 if (r_texture_fogattenuation)
495 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
500 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
505 static void R_BuildFogHeightTexture(void)
507 unsigned char *inpixels;
515 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516 if (r_refdef.fogheighttexturename[0])
517 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
520 r_refdef.fog_height_tablesize = 0;
521 if (r_texture_fogheighttexture)
522 R_FreeTexture(r_texture_fogheighttexture);
523 r_texture_fogheighttexture = NULL;
524 if (r_refdef.fog_height_table2d)
525 Mem_Free(r_refdef.fog_height_table2d);
526 r_refdef.fog_height_table2d = NULL;
527 if (r_refdef.fog_height_table1d)
528 Mem_Free(r_refdef.fog_height_table1d);
529 r_refdef.fog_height_table1d = NULL;
533 r_refdef.fog_height_tablesize = size;
534 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
538 // LordHavoc: now the magic - what is that table2d for? it is a cooked
539 // average fog color table accounting for every fog layer between a point
540 // and the camera. (Note: attenuation is handled separately!)
541 for (y = 0;y < size;y++)
543 for (x = 0;x < size;x++)
549 for (j = x;j <= y;j++)
551 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
557 for (j = x;j >= y;j--)
559 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
564 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
570 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
573 //=======================================================================================================================================================
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
590 "#ifdef USESHADOWMAP2D\n"
591 "# ifdef GL_EXT_gpu_shader4\n"
592 "# extension GL_EXT_gpu_shader4 : enable\n"
594 "# ifdef GL_ARB_texture_gather\n"
595 "# extension GL_ARB_texture_gather : enable\n"
597 "# ifdef GL_AMD_texture_texture4\n"
598 "# extension GL_AMD_texture_texture4 : enable\n"
603 "//#ifdef USESHADOWSAMPLER\n"
604 "//# extension GL_ARB_shadow : enable\n"
607 "//#ifdef __GLSL_CG_DATA_TYPES\n"
608 "//# define myhalf half\n"
609 "//# define myhalf2 half2\n"
610 "//# define myhalf3 half3\n"
611 "//# define myhalf4 half4\n"
613 "# define myhalf float\n"
614 "# define myhalf2 vec2\n"
615 "# define myhalf3 vec3\n"
616 "# define myhalf4 vec4\n"
619 "#ifdef VERTEX_SHADER\n"
620 "uniform mat4 ModelViewProjectionMatrix;\n"
623 "#ifdef MODE_DEPTH_OR_SHADOW\n"
624 "#ifdef VERTEX_SHADER\n"
627 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
630 "#else // !MODE_DEPTH_ORSHADOW\n"
635 "#ifdef MODE_SHOWDEPTH\n"
636 "#ifdef VERTEX_SHADER\n"
639 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
640 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
644 "#ifdef FRAGMENT_SHADER\n"
647 " gl_FragColor = gl_Color;\n"
650 "#else // !MODE_SHOWDEPTH\n"
655 "#ifdef MODE_POSTPROCESS\n"
656 "varying vec2 TexCoord1;\n"
657 "varying vec2 TexCoord2;\n"
659 "#ifdef VERTEX_SHADER\n"
662 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
663 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
665 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "uniform sampler2D Texture_First;\n"
673 "uniform sampler2D Texture_Second;\n"
674 "uniform vec4 BloomColorSubtract;\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
694 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
696 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
698 "#ifdef USEVIEWTINT\n"
699 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// 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"
705 " float sobel = 1.0;\n"
706 " // vec2 ts = textureSize(Texture_First, 0);\n"
707 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 " vec2 px = PixelSize;\n"
709 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
711 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
714 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
717 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
720 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
738 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
739 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
743 "#ifdef USESATURATION\n"
744 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
750 "#ifdef USEGAMMARAMPS\n"
751 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
757 "#else // !MODE_POSTPROCESS\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
769 "#ifdef VERTEX_SHADER\n"
772 " gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
776 "#ifdef USESPECULAR\n"
777 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
779 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
793 " gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
798 "#ifdef USESPECULAR\n"
799 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 " gl_FragColor *= tex2;\n"
804 " gl_FragColor += tex2;\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
812 "#else // !MODE_GENERIC\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
822 " gl_FrontColor = gl_Color;\n"
823 " TexCoord = gl_MultiTexCoord0.xy;\n"
824 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
835 " vec2 tc = TexCoord;\n"
836 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 " tc += BloomBlur_Parameters.xy;\n"
838 " for (i = 1;i < SAMPLES;i++)\n"
840 " color += texture2D(Texture_First, tc).rgb;\n"
841 " tc += BloomBlur_Parameters.xy;\n"
843 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
855 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 " ModelViewProjectionPosition = gl_Position;\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
876 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 " // FIXME temporary hack to detect the case that the reflection\n"
881 " // gets blackened at edges due to leaving the area that contains actual\n"
883 " // Remove this 'ack once we have a better way to stop this thing from\n"
885 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
893 "#else // !MODE_REFRACTION\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
908 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 " ModelViewProjectionPosition = gl_Position;\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
933 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
934 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
935 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
936 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
937 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
938 " // FIXME temporary hack to detect the case that the reflection\n"
939 " // gets blackened at edges due to leaving the area that contains actual\n"
941 " // Remove this 'ack once we have a better way to stop this thing from\n"
943 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
948 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
949 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
950 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
951 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
952 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
953 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
954 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
957 "#else // !MODE_WATER\n"
962 "// common definitions between vertex shader and fragment shader:\n"
964 "varying vec2 TexCoord;\n"
965 "#ifdef USEVERTEXTEXTUREBLEND\n"
966 "varying vec2 TexCoord2;\n"
968 "#ifdef USELIGHTMAP\n"
969 "varying vec2 TexCoordLightmap;\n"
972 "#ifdef MODE_LIGHTSOURCE\n"
973 "varying vec3 CubeVector;\n"
976 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
977 "varying vec3 LightVector;\n"
980 "#ifdef USEEYEVECTOR\n"
981 "varying vec3 EyeVector;\n"
984 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
987 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
988 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
989 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
990 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
993 "#ifdef USEREFLECTION\n"
994 "varying vec4 ModelViewProjectionPosition;\n"
996 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
998 "varying vec4 ModelViewPosition;\n"
1001 "#ifdef MODE_LIGHTSOURCE\n"
1002 "uniform vec3 LightPosition;\n"
1004 "uniform vec3 EyePosition;\n"
1005 "#ifdef MODE_LIGHTDIRECTION\n"
1006 "uniform vec3 LightDir;\n"
1008 "uniform vec4 FogPlane;\n"
1010 "#ifdef USESHADOWMAPORTHO\n"
1011 "varying vec3 ShadowMapTC;\n"
1018 "// 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"
1020 "// fragment shader specific:\n"
1021 "#ifdef FRAGMENT_SHADER\n"
1023 "uniform sampler2D Texture_Normal;\n"
1024 "uniform sampler2D Texture_Color;\n"
1025 "uniform sampler2D Texture_Gloss;\n"
1027 "uniform sampler2D Texture_Glow;\n"
1029 "#ifdef USEVERTEXTEXTUREBLEND\n"
1030 "uniform sampler2D Texture_SecondaryNormal;\n"
1031 "uniform sampler2D Texture_SecondaryColor;\n"
1032 "uniform sampler2D Texture_SecondaryGloss;\n"
1034 "uniform sampler2D Texture_SecondaryGlow;\n"
1037 "#ifdef USECOLORMAPPING\n"
1038 "uniform sampler2D Texture_Pants;\n"
1039 "uniform sampler2D Texture_Shirt;\n"
1042 "#ifdef USEFOGHEIGHTTEXTURE\n"
1043 "uniform sampler2D Texture_FogHeightTexture;\n"
1045 "uniform sampler2D Texture_FogMask;\n"
1047 "#ifdef USELIGHTMAP\n"
1048 "uniform sampler2D Texture_Lightmap;\n"
1050 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1051 "uniform sampler2D Texture_Deluxemap;\n"
1053 "#ifdef USEREFLECTION\n"
1054 "uniform sampler2D Texture_Reflection;\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform sampler2D Texture_ScreenDepth;\n"
1059 "uniform sampler2D Texture_ScreenNormalMap;\n"
1061 "#ifdef USEDEFERREDLIGHTMAP\n"
1062 "uniform sampler2D Texture_ScreenDiffuse;\n"
1063 "uniform sampler2D Texture_ScreenSpecular;\n"
1066 "uniform myhalf3 Color_Pants;\n"
1067 "uniform myhalf3 Color_Shirt;\n"
1068 "uniform myhalf3 FogColor;\n"
1071 "uniform float FogRangeRecip;\n"
1072 "uniform float FogPlaneViewDist;\n"
1073 "uniform float FogHeightFade;\n"
1074 "vec3 FogVertex(vec3 surfacecolor)\n"
1076 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1077 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1081 " fogfrac = fogheightpixel.a;\n"
1082 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1084 "# ifdef USEFOGOUTSIDE\n"
1085 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1087 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1089 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1094 "#ifdef USEOFFSETMAPPING\n"
1095 "uniform float OffsetMapping_Scale;\n"
1096 "vec2 OffsetMapping(vec2 TexCoord)\n"
1098 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1099 " // 14 sample relief mapping: linear search and then binary search\n"
1100 " // this basically steps forward a small amount repeatedly until it finds\n"
1101 " // itself inside solid, then jitters forward and back using decreasing\n"
1102 " // amounts to find the impact\n"
1103 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1104 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1105 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1106 " vec3 RT = vec3(TexCoord, 1);\n"
1107 " OffsetVector *= 0.1;\n"
1108 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1113 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1114 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1115 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1116 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1118 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1119 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1120 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1121 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1124 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1125 " // this basically moves forward the full distance, and then backs up based\n"
1126 " // on height of samples\n"
1127 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1128 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1129 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1130 " TexCoord += OffsetVector;\n"
1131 " OffsetVector *= 0.333;\n"
1132 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1133 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1134 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1135 " return TexCoord;\n"
1138 "#endif // USEOFFSETMAPPING\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1141 "uniform sampler2D Texture_Attenuation;\n"
1142 "uniform samplerCube Texture_Cube;\n"
1145 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1147 "#ifdef USESHADOWMAP2D\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1151 "uniform sampler2D Texture_ShadowMap2D;\n"
1155 "#ifdef USESHADOWMAPVSDCT\n"
1156 "uniform samplerCube Texture_CubeProjection;\n"
1159 "#if defined(USESHADOWMAP2D)\n"
1160 "uniform vec2 ShadowMap_TextureScale;\n"
1161 "uniform vec4 ShadowMap_Parameters;\n"
1164 "#if defined(USESHADOWMAP2D)\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1168 "# ifdef USESHADOWMAPVSDCT\n"
1169 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1171 " vec3 adir = abs(dir);\n"
1172 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1173 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1177 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1179 " vec3 adir = abs(dir);\n"
1180 " float ma = adir.z;\n"
1181 " vec4 proj = vec4(dir, 2.5);\n"
1182 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1183 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1184 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1185 " 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"
1189 "#endif // defined(USESHADOWMAP2D)\n"
1191 "# ifdef USESHADOWMAP2D\n"
1192 "float ShadowMapCompare(vec3 dir)\n"
1194 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1197 "# ifdef USESHADOWSAMPLER\n"
1198 "# ifdef USESHADOWMAPPCF\n"
1199 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1200 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1201 " 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"
1203 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1206 "# ifdef USESHADOWMAPPCF\n"
1207 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1208 "# ifdef GL_ARB_texture_gather\n"
1209 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1211 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1213 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1214 "# if USESHADOWMAPPCF > 1\n"
1215 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1216 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1217 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1218 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1219 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1220 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1221 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1222 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1223 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1224 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1225 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1226 " locols.yz += group2.ab;\n"
1227 " hicols.yz += group8.rg;\n"
1228 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1229 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1230 " mix(locols, hicols, offset.y);\n"
1231 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1232 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1233 " f = dot(cols, vec4(1.0/25.0));\n"
1235 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1236 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1237 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1238 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1239 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1240 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1241 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1244 "# ifdef GL_EXT_gpu_shader4\n"
1245 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1247 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1249 "# if USESHADOWMAPPCF > 1\n"
1250 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1251 " center *= ShadowMap_TextureScale;\n"
1252 " 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"
1253 " 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"
1254 " 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"
1255 " 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"
1256 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1257 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1259 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1260 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1261 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1262 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1263 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1264 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1268 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1271 "# ifdef USESHADOWMAPORTHO\n"
1272 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1278 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1279 "#endif // FRAGMENT_SHADER\n"
1284 "#ifdef MODE_DEFERREDGEOMETRY\n"
1285 "#ifdef VERTEX_SHADER\n"
1286 "uniform mat4 TexMatrix;\n"
1287 "#ifdef USEVERTEXTEXTUREBLEND\n"
1288 "uniform mat4 BackgroundTexMatrix;\n"
1290 "uniform mat4 ModelViewMatrix;\n"
1293 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1294 "#ifdef USEVERTEXTEXTUREBLEND\n"
1295 " gl_FrontColor = gl_Color;\n"
1296 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1299 " // transform unnormalized eye direction into tangent space\n"
1300 "#ifdef USEOFFSETMAPPING\n"
1301 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1302 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1303 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1304 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1307 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1308 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1309 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1310 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1312 "#endif // VERTEX_SHADER\n"
1314 "#ifdef FRAGMENT_SHADER\n"
1317 "#ifdef USEOFFSETMAPPING\n"
1318 " // apply offsetmapping\n"
1319 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1320 "#define TexCoord TexCoordOffset\n"
1323 "#ifdef USEALPHAKILL\n"
1324 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1330 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1331 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1332 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1337 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1339 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1340 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1343 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1345 "#endif // FRAGMENT_SHADER\n"
1346 "#else // !MODE_DEFERREDGEOMETRY\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "#ifdef VERTEX_SHADER\n"
1353 "uniform mat4 ModelViewMatrix;\n"
1356 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1357 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1359 "#endif // VERTEX_SHADER\n"
1361 "#ifdef FRAGMENT_SHADER\n"
1362 "uniform mat4 ViewToLight;\n"
1363 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1364 "uniform vec2 ScreenToDepth;\n"
1365 "uniform myhalf3 DeferredColor_Ambient;\n"
1366 "uniform myhalf3 DeferredColor_Diffuse;\n"
1367 "#ifdef USESPECULAR\n"
1368 "uniform myhalf3 DeferredColor_Specular;\n"
1369 "uniform myhalf SpecularPower;\n"
1371 "uniform myhalf2 PixelToScreenTexCoord;\n"
1374 " // calculate viewspace pixel position\n"
1375 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1377 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1378 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1379 " // decode viewspace pixel normal\n"
1380 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1381 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1382 " // surfacenormal = pixel normal in viewspace\n"
1383 " // LightVector = pixel to light in viewspace\n"
1384 " // CubeVector = position in lightspace\n"
1385 " // eyevector = pixel to view in viewspace\n"
1386 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1387 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1388 "#ifdef USEDIFFUSE\n"
1389 " // calculate diffuse shading\n"
1390 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1391 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1393 "#ifdef USESPECULAR\n"
1394 " // calculate directional shading\n"
1395 " vec3 eyevector = position * -1.0;\n"
1396 "# ifdef USEEXACTSPECULARMATH\n"
1397 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1399 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1400 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1404 "#if defined(USESHADOWMAP2D)\n"
1405 " fade *= ShadowMapCompare(CubeVector);\n"
1408 "#ifdef USEDIFFUSE\n"
1409 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1411 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1413 "#ifdef USESPECULAR\n"
1414 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1416 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1419 "# ifdef USECUBEFILTER\n"
1420 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1421 " gl_FragData[0].rgb *= cubecolor;\n"
1422 " gl_FragData[1].rgb *= cubecolor;\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1431 "#ifdef VERTEX_SHADER\n"
1432 "uniform mat4 TexMatrix;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 "uniform mat4 BackgroundTexMatrix;\n"
1436 "#ifdef MODE_LIGHTSOURCE\n"
1437 "uniform mat4 ModelToLight;\n"
1439 "#ifdef USESHADOWMAPORTHO\n"
1440 "uniform mat4 ShadowMapMatrix;\n"
1444 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1445 " gl_FrontColor = gl_Color;\n"
1447 " // copy the surface texcoord\n"
1448 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1449 "#ifdef USEVERTEXTEXTUREBLEND\n"
1450 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1452 "#ifdef USELIGHTMAP\n"
1453 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 " // transform vertex position into light attenuation/cubemap space\n"
1458 " // (-1 to +1 across the light box)\n"
1459 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1461 "# ifdef USEDIFFUSE\n"
1462 " // transform unnormalized light direction into tangent space\n"
1463 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1464 " // normalize it per pixel)\n"
1465 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1466 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1467 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1468 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1472 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1473 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1474 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1475 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1478 " // transform unnormalized eye direction into tangent space\n"
1479 "#ifdef USEEYEVECTOR\n"
1480 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1481 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1482 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1483 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1487 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1488 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1491 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1492 " VectorS = gl_MultiTexCoord1.xyz;\n"
1493 " VectorT = gl_MultiTexCoord2.xyz;\n"
1494 " VectorR = gl_MultiTexCoord3.xyz;\n"
1497 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1498 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1500 "#ifdef USESHADOWMAPORTHO\n"
1501 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1504 "#ifdef USEREFLECTION\n"
1505 " ModelViewProjectionPosition = gl_Position;\n"
1508 "#endif // VERTEX_SHADER\n"
1513 "#ifdef FRAGMENT_SHADER\n"
1514 "#ifdef USEDEFERREDLIGHTMAP\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "uniform myhalf3 DeferredMod_Diffuse;\n"
1517 "uniform myhalf3 DeferredMod_Specular;\n"
1519 "uniform myhalf3 Color_Ambient;\n"
1520 "uniform myhalf3 Color_Diffuse;\n"
1521 "uniform myhalf3 Color_Specular;\n"
1522 "uniform myhalf SpecularPower;\n"
1524 "uniform myhalf3 Color_Glow;\n"
1526 "uniform myhalf Alpha;\n"
1527 "#ifdef USEREFLECTION\n"
1528 "uniform vec4 DistortScaleRefractReflect;\n"
1529 "uniform vec4 ScreenScaleRefractReflect;\n"
1530 "uniform vec4 ScreenCenterRefractReflect;\n"
1531 "uniform myhalf4 ReflectColor;\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "uniform mat4 ModelToReflectCube;\n"
1535 "uniform sampler2D Texture_ReflectMask;\n"
1536 "uniform samplerCube Texture_ReflectCube;\n"
1538 "#ifdef MODE_LIGHTDIRECTION\n"
1539 "uniform myhalf3 LightColor;\n"
1541 "#ifdef MODE_LIGHTSOURCE\n"
1542 "uniform myhalf3 LightColor;\n"
1546 "#ifdef USEOFFSETMAPPING\n"
1547 " // apply offsetmapping\n"
1548 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1549 "#define TexCoord TexCoordOffset\n"
1552 " // combine the diffuse textures (base, pants, shirt)\n"
1553 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1554 "#ifdef USEALPHAKILL\n"
1555 " if (color.a < 0.5)\n"
1558 " color.a *= Alpha;\n"
1559 "#ifdef USECOLORMAPPING\n"
1560 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1562 "#ifdef USEVERTEXTEXTUREBLEND\n"
1563 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1564 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1565 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1566 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1568 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1571 " // get the surface normal\n"
1572 "#ifdef USEVERTEXTEXTUREBLEND\n"
1573 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1575 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1578 " // get the material colors\n"
1579 " myhalf3 diffusetex = color.rgb;\n"
1580 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1581 "# ifdef USEVERTEXTEXTUREBLEND\n"
1582 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1584 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1588 "#ifdef USEREFLECTCUBE\n"
1589 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1590 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1591 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1592 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1598 "#ifdef MODE_LIGHTSOURCE\n"
1599 " // light source\n"
1600 "#ifdef USEDIFFUSE\n"
1601 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1603 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1604 "#ifdef USESPECULAR\n"
1605 "#ifdef USEEXACTSPECULARMATH\n"
1606 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1608 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1609 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1611 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1614 " color.rgb = diffusetex * Color_Ambient;\n"
1616 " color.rgb *= LightColor;\n"
1617 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1618 "#if defined(USESHADOWMAP2D)\n"
1619 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1621 "# ifdef USECUBEFILTER\n"
1622 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1624 "#endif // MODE_LIGHTSOURCE\n"
1629 "#ifdef MODE_LIGHTDIRECTION\n"
1631 "#ifdef USEDIFFUSE\n"
1632 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1634 "#define lightcolor LightColor\n"
1635 "#endif // MODE_LIGHTDIRECTION\n"
1636 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1638 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1639 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1640 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1641 " // convert modelspace light vector to tangentspace\n"
1642 " myhalf3 lightnormal;\n"
1643 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1644 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1645 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1646 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1647 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1648 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1649 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1650 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1651 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1652 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1653 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1654 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1655 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1656 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1659 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1660 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1661 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1667 "#ifdef MODE_LIGHTMAP\n"
1668 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1669 "#endif // MODE_LIGHTMAP\n"
1670 "#ifdef MODE_VERTEXCOLOR\n"
1671 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1672 "#endif // MODE_VERTEXCOLOR\n"
1673 "#ifdef MODE_FLATCOLOR\n"
1674 " color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif // MODE_FLATCOLOR\n"
1681 "# ifdef USEDIFFUSE\n"
1682 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "# ifdef USESPECULAR\n"
1684 "# ifdef USEEXACTSPECULARMATH\n"
1685 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1687 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1688 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1690 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1692 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1695 " color.rgb = diffusetex * Color_Ambient;\n"
1699 "#ifdef USESHADOWMAPORTHO\n"
1700 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1703 "#ifdef USEDEFERREDLIGHTMAP\n"
1704 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1705 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1706 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1710 "#ifdef USEVERTEXTEXTUREBLEND\n"
1711 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1713 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1718 " color.rgb = FogVertex(color.rgb);\n"
1721 " // 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"
1722 "#ifdef USEREFLECTION\n"
1723 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1724 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1725 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1726 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1727 " // FIXME temporary hack to detect the case that the reflection\n"
1728 " // gets blackened at edges due to leaving the area that contains actual\n"
1730 " // Remove this 'ack once we have a better way to stop this thing from\n"
1732 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1733 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1734 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1735 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1736 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1737 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1740 " gl_FragColor = vec4(color);\n"
1742 "#endif // FRAGMENT_SHADER\n"
1744 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1745 "#endif // !MODE_DEFERREDGEOMETRY\n"
1746 "#endif // !MODE_WATER\n"
1747 "#endif // !MODE_REFRACTION\n"
1748 "#endif // !MODE_BLOOMBLUR\n"
1749 "#endif // !MODE_GENERIC\n"
1750 "#endif // !MODE_POSTPROCESS\n"
1751 "#endif // !MODE_SHOWDEPTH\n"
1752 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1756 =========================================================================================================================================================
1760 =========================================================================================================================================================
1764 =========================================================================================================================================================
1768 =========================================================================================================================================================
1772 =========================================================================================================================================================
1776 =========================================================================================================================================================
1780 =========================================================================================================================================================
1783 const char *builtincgshaderstring =
1784 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1785 "// written by Forest 'LordHavoc' Hale\n"
1786 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1788 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1789 "#if defined(USEREFLECTION)\n"
1790 "#undef USESHADOWMAPORTHO\n"
1793 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1796 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1797 "#define USELIGHTMAP\n"
1799 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1800 "#define USEEYEVECTOR\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1805 "//#undef USESHADOWMAPPCF\n"
1806 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1807 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1809 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1813 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1814 "#ifdef VERTEX_SHADER\n"
1817 "float4 gl_Vertex : POSITION,\n"
1818 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1819 "out float4 gl_Position : POSITION,\n"
1820 "out float Depth : TEXCOORD0\n"
1823 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1824 " Depth = gl_Position.z;\n"
1828 "#ifdef FRAGMENT_SHADER\n"
1831 "float Depth : TEXCOORD0,\n"
1832 "out float4 gl_FragColor : COLOR\n"
1835 "// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1836 " float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1837 " temp.yz -= floor(temp.yz);\n"
1838 " gl_FragColor = float4(temp,0);\n"
1839 "// gl_FragColor = float4(Depth,0,0,0);\n"
1842 "#else // !MODE_DEPTH_ORSHADOW\n"
1847 "#ifdef MODE_SHOWDEPTH\n"
1848 "#ifdef VERTEX_SHADER\n"
1851 "float4 gl_Vertex : POSITION,\n"
1852 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1853 "out float4 gl_Position : POSITION,\n"
1854 "out float4 gl_FrontColor : COLOR0\n"
1857 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1858 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1862 "#ifdef FRAGMENT_SHADER\n"
1865 "float4 gl_FrontColor : COLOR0,\n"
1866 "out float4 gl_FragColor : COLOR\n"
1869 " gl_FragColor = gl_FrontColor;\n"
1872 "#else // !MODE_SHOWDEPTH\n"
1877 "#ifdef MODE_POSTPROCESS\n"
1879 "#ifdef VERTEX_SHADER\n"
1882 "float4 gl_Vertex : POSITION,\n"
1883 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1884 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1885 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1886 "out float4 gl_Position : POSITION,\n"
1887 "out float2 TexCoord1 : TEXCOORD0,\n"
1888 "out float2 TexCoord2 : TEXCOORD1\n"
1891 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1892 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1894 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1899 "#ifdef FRAGMENT_SHADER\n"
1902 "float2 TexCoord1 : TEXCOORD0,\n"
1903 "float2 TexCoord2 : TEXCOORD1,\n"
1904 "uniform sampler Texture_First : register(s0),\n"
1906 "uniform sampler Texture_Second : register(s1),\n"
1908 "#ifdef USEGAMMARAMPS\n"
1909 "uniform sampler Texture_GammaRamps : register(s2),\n"
1911 "#ifdef USESATURATION\n"
1912 "uniform float Saturation : register(c30),\n"
1914 "#ifdef USEVIEWTINT\n"
1915 "uniform float4 ViewTintColor : register(c41),\n"
1917 "uniform float4 UserVec1 : register(c37),\n"
1918 "uniform float4 UserVec2 : register(c38),\n"
1919 "uniform float4 UserVec3 : register(c39),\n"
1920 "uniform float4 UserVec4 : register(c40),\n"
1921 "uniform float ClientTime : register(c2),\n"
1922 "uniform float2 PixelSize : register(c25),\n"
1923 "uniform float4 BloomColorSubtract : register(c43),\n"
1924 "out float4 gl_FragColor : COLOR\n"
1927 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1929 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1931 "#ifdef USEVIEWTINT\n"
1932 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1935 "#ifdef USEPOSTPROCESSING\n"
1936 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1937 "// 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"
1938 " float sobel = 1.0;\n"
1939 " // float2 ts = textureSize(Texture_First, 0);\n"
1940 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1941 " float2 px = PixelSize;\n"
1942 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1943 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1944 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1945 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1946 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1947 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1948 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1949 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1950 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1951 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1952 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1953 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1954 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1955 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1956 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1957 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1958 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1959 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1960 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1961 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1962 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1963 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1964 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1965 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1966 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1967 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1968 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1969 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1970 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1971 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1972 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
1973 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
1976 "#ifdef USESATURATION\n"
1977 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1978 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1979 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1980 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
1983 "#ifdef USEGAMMARAMPS\n"
1984 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1985 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1986 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1990 "#else // !MODE_POSTPROCESS\n"
1995 "#ifdef MODE_GENERIC\n"
1996 "#ifdef VERTEX_SHADER\n"
1999 "float4 gl_Vertex : POSITION,\n"
2000 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2001 "float4 gl_Color : COLOR0,\n"
2002 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2003 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2004 "out float4 gl_Position : POSITION,\n"
2005 "out float4 gl_FrontColor : COLOR,\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "out float2 TexCoord2 : TEXCOORD1\n"
2011 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2013 " gl_FrontColor = gl_Color; // Cg is forward\n"
2015 "#ifdef USEDIFFUSE\n"
2016 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2018 "#ifdef USESPECULAR\n"
2019 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2021 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2025 "#ifdef FRAGMENT_SHADER\n"
2029 "float4 gl_FrontColor : COLOR0,\n"
2030 "float2 TexCoord1 : TEXCOORD0,\n"
2031 "float2 TexCoord2 : TEXCOORD1,\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2035 "#ifdef USESPECULAR\n"
2036 "uniform sampler Texture_Second : register(s1),\n"
2038 "out float4 gl_FragColor : COLOR\n"
2041 " gl_FragColor = gl_FrontColor;\n"
2042 "#ifdef USEDIFFUSE\n"
2043 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2046 "#ifdef USESPECULAR\n"
2047 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2048 "# ifdef USECOLORMAPPING\n"
2049 " gl_FragColor *= tex2;\n"
2052 " gl_FragColor += tex2;\n"
2054 "# ifdef USEVERTEXTEXTUREBLEND\n"
2055 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2060 "#else // !MODE_GENERIC\n"
2065 "#ifdef MODE_BLOOMBLUR\n"
2066 "#ifdef VERTEX_SHADER\n"
2069 "float4 gl_Vertex : POSITION,\n"
2070 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2071 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2072 "out float4 gl_Position : POSITION,\n"
2073 "out float2 TexCoord : TEXCOORD0\n"
2076 " TexCoord = gl_MultiTexCoord0.xy;\n"
2077 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2085 "float2 TexCoord : TEXCOORD0,\n"
2086 "uniform sampler Texture_First : register(s0),\n"
2087 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2088 "out float4 gl_FragColor : COLOR\n"
2092 " float2 tc = TexCoord;\n"
2093 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2094 " tc += BloomBlur_Parameters.xy;\n"
2095 " for (i = 1;i < SAMPLES;i++)\n"
2097 " color += tex2D(Texture_First, tc).rgb;\n"
2098 " tc += BloomBlur_Parameters.xy;\n"
2100 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2103 "#else // !MODE_BLOOMBLUR\n"
2104 "#ifdef MODE_REFRACTION\n"
2105 "#ifdef VERTEX_SHADER\n"
2108 "float4 gl_Vertex : POSITION,\n"
2109 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2110 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2111 "uniform float4x4 TexMatrix : register(c0),\n"
2112 "uniform float3 EyePosition : register(c24),\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0,\n"
2115 "out float3 EyeVector : TEXCOORD1,\n"
2116 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2119 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2120 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 " ModelViewProjectionPosition = gl_Position;\n"
2125 "#ifdef FRAGMENT_SHADER\n"
2128 "float2 TexCoord : TEXCOORD0,\n"
2129 "float3 EyeVector : TEXCOORD1,\n"
2130 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2131 "uniform sampler Texture_Normal : register(s0),\n"
2132 "uniform sampler Texture_Refraction : register(s3),\n"
2133 "uniform sampler Texture_Reflection : register(s7),\n"
2134 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2135 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2136 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2137 "uniform float4 RefractColor : register(c29),\n"
2138 "out float4 gl_FragColor : COLOR\n"
2141 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2142 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2143 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2144 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2145 " // FIXME temporary hack to detect the case that the reflection\n"
2146 " // gets blackened at edges due to leaving the area that contains actual\n"
2148 " // Remove this 'ack once we have a better way to stop this thing from\n"
2150 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2151 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2152 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2153 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2154 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2155 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2158 "#else // !MODE_REFRACTION\n"
2163 "#ifdef MODE_WATER\n"
2164 "#ifdef VERTEX_SHADER\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2172 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2173 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2174 "uniform float4x4 TexMatrix : register(c0),\n"
2175 "uniform float3 EyePosition : register(c24),\n"
2176 "out float4 gl_Position : POSITION,\n"
2177 "out float2 TexCoord : TEXCOORD0,\n"
2178 "out float3 EyeVector : TEXCOORD1,\n"
2179 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2182 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2183 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2184 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2185 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2186 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2187 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2188 " ModelViewProjectionPosition = gl_Position;\n"
2192 "#ifdef FRAGMENT_SHADER\n"
2195 "float2 TexCoord : TEXCOORD0,\n"
2196 "float3 EyeVector : TEXCOORD1,\n"
2197 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2198 "uniform sampler Texture_Normal : register(s0),\n"
2199 "uniform sampler Texture_Refraction : register(s3),\n"
2200 "uniform sampler Texture_Reflection : register(s7),\n"
2201 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2202 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2203 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2204 "uniform float4 RefractColor : register(c29),\n"
2205 "uniform float4 ReflectColor : register(c26),\n"
2206 "uniform float ReflectFactor : register(c27),\n"
2207 "uniform float ReflectOffset : register(c28),\n"
2208 "out float4 gl_FragColor : COLOR\n"
2211 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2212 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2213 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2214 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2215 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2216 " // FIXME temporary hack to detect the case that the reflection\n"
2217 " // gets blackened at edges due to leaving the area that contains actual\n"
2219 " // Remove this 'ack once we have a better way to stop this thing from\n"
2221 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2222 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2223 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2224 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2225 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2226 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2227 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2228 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2229 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2230 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2231 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2232 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2235 "#else // !MODE_WATER\n"
2240 "// 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"
2242 "// fragment shader specific:\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2246 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2249 "#ifdef USEFOGHEIGHTTEXTURE\n"
2250 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2251 " fogfrac = fogheightpixel.a;\n"
2252 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2254 "# ifdef USEFOGOUTSIDE\n"
2255 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2257 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2259 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2264 "#ifdef USEOFFSETMAPPING\n"
2265 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2267 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2268 " // 14 sample relief mapping: linear search and then binary search\n"
2269 " // this basically steps forward a small amount repeatedly until it finds\n"
2270 " // itself inside solid, then jitters forward and back using decreasing\n"
2271 " // amounts to find the impact\n"
2272 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2273 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2274 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2275 " float3 RT = float3(TexCoord, 1);\n"
2276 " OffsetVector *= 0.1;\n"
2277 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2278 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2279 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2280 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2281 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2282 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2283 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2284 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2285 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2286 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2287 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2288 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2289 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2290 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2293 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2294 " // this basically moves forward the full distance, and then backs up based\n"
2295 " // on height of samples\n"
2296 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2297 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2298 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2299 " TexCoord += OffsetVector;\n"
2300 " OffsetVector *= 0.333;\n"
2301 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2302 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2303 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2304 " return TexCoord;\n"
2307 "#endif // USEOFFSETMAPPING\n"
2309 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2310 "#if defined(USESHADOWMAP2D)\n"
2311 "# ifdef USESHADOWMAPORTHO\n"
2312 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2314 "# ifdef USESHADOWMAPVSDCT\n"
2315 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2317 " float3 adir = abs(dir);\n"
2318 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2319 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2320 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2323 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2325 " float3 adir = abs(dir);\n"
2326 " float ma = adir.z;\n"
2327 " float4 proj = float4(dir, 2.5);\n"
2328 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2329 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2331 " return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2333 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2334 " 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"
2339 "#endif // defined(USESHADOWMAP2D)\n"
2341 "# ifdef USESHADOWMAP2D\n"
2342 "#ifdef USESHADOWMAPVSDCT\n"
2343 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2345 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2348 "#ifdef USESHADOWMAPVSDCT\n"
2349 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2351 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2355 "# ifdef USESHADOWSAMPLER\n"
2356 "# ifdef USESHADOWMAPPCF\n"
2357 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2358 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2359 " f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2361 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2364 "# ifdef USESHADOWMAPPCF\n"
2365 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2366 "# ifdef GL_ARB_texture_gather\n"
2367 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2369 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2371 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2372 "# if USESHADOWMAPPCF > 1\n"
2373 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2374 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2375 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2376 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2377 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2378 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2379 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2380 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2381 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2382 " float4 locols = float4(group1.ab, group3.ab);\n"
2383 " float4 hicols = float4(group7.rg, group9.rg);\n"
2384 " locols.yz += group2.ab;\n"
2385 " hicols.yz += group8.rg;\n"
2386 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2387 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2388 " lerp(locols, hicols, offset.y);\n"
2389 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2390 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2391 " f = dot(cols, float4(1.0/25.0));\n"
2393 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2394 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2395 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2396 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2397 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2398 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2399 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2402 "# ifdef GL_EXT_gpu_shader4\n"
2403 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2405 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2407 "# if USESHADOWMAPPCF > 1\n"
2408 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2409 " center *= ShadowMap_TextureScale;\n"
2410 " 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"
2411 " 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"
2412 " 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"
2413 " 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"
2414 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2415 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2417 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2418 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2419 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2420 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2421 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2422 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2426 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2429 "# ifdef USESHADOWMAPORTHO\n"
2430 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2436 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2437 "#endif // FRAGMENT_SHADER\n"
2442 "#ifdef MODE_DEFERREDGEOMETRY\n"
2443 "#ifdef VERTEX_SHADER\n"
2446 "float4 gl_Vertex : POSITION,\n"
2447 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "float4 gl_Color : COLOR0,\n"
2451 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2452 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2453 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2454 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2455 "uniform float4x4 TexMatrix : register(c0),\n"
2456 "#ifdef USEVERTEXTEXTUREBLEND\n"
2457 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2459 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2460 "#ifdef USEOFFSETMAPPING\n"
2461 "uniform float3 EyePosition : register(c24),\n"
2463 "out float4 gl_Position : POSITION,\n"
2464 "out float4 gl_FrontColor : COLOR,\n"
2465 "out float4 TexCoordBoth : TEXCOORD0,\n"
2466 "#ifdef USEOFFSETMAPPING\n"
2467 "out float3 EyeVector : TEXCOORD2,\n"
2469 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2470 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2471 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2474 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2475 "#ifdef USEVERTEXTEXTUREBLEND\n"
2477 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2479 " gl_FrontColor = gl_Color; // Cg is forward\n"
2481 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2484 " // transform unnormalized eye direction into tangent space\n"
2485 "#ifdef USEOFFSETMAPPING\n"
2486 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2487 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2488 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2489 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2492 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2493 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2494 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2495 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2497 "#endif // VERTEX_SHADER\n"
2499 "#ifdef FRAGMENT_SHADER\n"
2502 "float4 TexCoordBoth : TEXCOORD0,\n"
2503 "float3 EyeVector : TEXCOORD2,\n"
2504 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2505 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2506 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2507 "uniform sampler Texture_Normal : register(s0),\n"
2508 "#ifdef USEALPHAKILL\n"
2509 "uniform sampler Texture_Color : register(s1),\n"
2511 "uniform sampler Texture_Gloss : register(s2),\n"
2512 "#ifdef USEVERTEXTEXTUREBLEND\n"
2513 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2514 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2516 "#ifdef USEOFFSETMAPPING\n"
2517 "uniform float OffsetMapping_Scale : register(c24),\n"
2519 "uniform half SpecularPower : register(c36),\n"
2520 "out float4 gl_FragColor : COLOR\n"
2523 " float2 TexCoord = TexCoordBoth.xy;\n"
2524 "#ifdef USEOFFSETMAPPING\n"
2525 " // apply offsetmapping\n"
2526 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2527 "#define TexCoord TexCoordOffset\n"
2530 "#ifdef USEALPHAKILL\n"
2531 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2535 "#ifdef USEVERTEXTEXTUREBLEND\n"
2536 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2537 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2538 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2539 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2542 "#ifdef USEVERTEXTEXTUREBLEND\n"
2543 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2544 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2546 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2547 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2550 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2552 "#endif // FRAGMENT_SHADER\n"
2553 "#else // !MODE_DEFERREDGEOMETRY\n"
2558 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2559 "#ifdef VERTEX_SHADER\n"
2562 "float4 gl_Vertex : POSITION,\n"
2563 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2564 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2565 "out float4 gl_Position : POSITION,\n"
2566 "out float4 ModelViewPosition : TEXCOORD0\n"
2569 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2570 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2572 "#endif // VERTEX_SHADER\n"
2574 "#ifdef FRAGMENT_SHADER\n"
2578 "float2 Pixel : VPOS,\n"
2580 "float2 Pixel : WPOS,\n"
2582 "float4 ModelViewPosition : TEXCOORD0,\n"
2583 "uniform float4x4 ViewToLight : register(c44),\n"
2584 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2585 "uniform float3 LightPosition : register(c23),\n"
2586 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2587 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2588 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2589 "#ifdef USESPECULAR\n"
2590 "uniform half3 DeferredColor_Specular : register(c11),\n"
2591 "uniform half SpecularPower : register(c36),\n"
2593 "uniform sampler Texture_Attenuation : register(s9),\n"
2594 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2595 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2597 "#ifdef USECUBEFILTER\n"
2598 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2601 "#ifdef USESHADOWMAP2D\n"
2602 "# ifdef USESHADOWSAMPLER\n"
2603 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2605 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2609 "#ifdef USESHADOWMAPVSDCT\n"
2610 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2613 "#if defined(USESHADOWMAP2D)\n"
2614 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2615 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2618 "out float4 gl_FragData0 : COLOR0,\n"
2619 "out float4 gl_FragData1 : COLOR1\n"
2622 " // calculate viewspace pixel position\n"
2623 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2624 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2625 " float3 position;\n"
2626 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2627 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2628 " // decode viewspace pixel normal\n"
2629 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2630 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2631 " // surfacenormal = pixel normal in viewspace\n"
2632 " // LightVector = pixel to light in viewspace\n"
2633 " // CubeVector = position in lightspace\n"
2634 " // eyevector = pixel to view in viewspace\n"
2635 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2636 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2637 "#ifdef USEDIFFUSE\n"
2638 " // calculate diffuse shading\n"
2639 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2640 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2642 "#ifdef USESPECULAR\n"
2643 " // calculate directional shading\n"
2644 " float3 eyevector = position * -1.0;\n"
2645 "# ifdef USEEXACTSPECULARMATH\n"
2646 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2648 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2649 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2653 "#if defined(USESHADOWMAP2D)\n"
2654 " fade *= ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2655 "#ifdef USESHADOWMAPVSDCT\n"
2656 ", Texture_CubeProjection\n"
2661 "#ifdef USEDIFFUSE\n"
2662 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2664 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2666 "#ifdef USESPECULAR\n"
2667 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2669 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2672 "# ifdef USECUBEFILTER\n"
2673 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2674 " gl_FragData0.rgb *= cubecolor;\n"
2675 " gl_FragData1.rgb *= cubecolor;\n"
2678 "#endif // FRAGMENT_SHADER\n"
2679 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2684 "#ifdef VERTEX_SHADER\n"
2687 "float4 gl_Vertex : POSITION,\n"
2688 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2689 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2690 "float4 gl_Color : COLOR0,\n"
2692 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2693 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2694 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2695 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2696 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2698 "uniform float3 EyePosition : register(c24),\n"
2699 "uniform float4x4 TexMatrix : register(c0),\n"
2700 "#ifdef USEVERTEXTEXTUREBLEND\n"
2701 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2703 "#ifdef MODE_LIGHTSOURCE\n"
2704 "uniform float4x4 ModelToLight : register(c20),\n"
2706 "#ifdef MODE_LIGHTSOURCE\n"
2707 "uniform float3 LightPosition : register(c27),\n"
2709 "#ifdef MODE_LIGHTDIRECTION\n"
2710 "uniform float3 LightDir : register(c26),\n"
2712 "uniform float4 FogPlane : register(c25),\n"
2713 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2714 "uniform float3 LightPosition : register(c27),\n"
2716 "#ifdef USESHADOWMAPORTHO\n"
2717 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2720 "out float4 gl_FrontColor : COLOR,\n"
2721 "out float4 TexCoordBoth : TEXCOORD0,\n"
2722 "#ifdef USELIGHTMAP\n"
2723 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2725 "#ifdef USEEYEVECTOR\n"
2726 "out float3 EyeVector : TEXCOORD2,\n"
2728 "#ifdef USEREFLECTION\n"
2729 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2732 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2734 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2735 "out float3 LightVector : TEXCOORD1,\n"
2737 "#ifdef MODE_LIGHTSOURCE\n"
2738 "out float3 CubeVector : TEXCOORD3,\n"
2740 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2741 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2742 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2743 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2745 "#ifdef USESHADOWMAPORTHO\n"
2746 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2748 "out float4 gl_Position : POSITION\n"
2751 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2753 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2755 " gl_FrontColor = gl_Color; // Cg is forward\n"
2758 " // copy the surface texcoord\n"
2759 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2760 "#ifdef USEVERTEXTEXTUREBLEND\n"
2761 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2763 "#ifdef USELIGHTMAP\n"
2764 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2767 "#ifdef MODE_LIGHTSOURCE\n"
2768 " // transform vertex position into light attenuation/cubemap space\n"
2769 " // (-1 to +1 across the light box)\n"
2770 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2772 "# ifdef USEDIFFUSE\n"
2773 " // transform unnormalized light direction into tangent space\n"
2774 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2775 " // normalize it per pixel)\n"
2776 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2777 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2778 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2779 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2783 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2784 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2785 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2786 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2789 " // transform unnormalized eye direction into tangent space\n"
2790 "#ifdef USEEYEVECTOR\n"
2791 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2792 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2793 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2794 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2798 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2799 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2802 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2803 " VectorS = gl_MultiTexCoord1.xyz;\n"
2804 " VectorT = gl_MultiTexCoord2.xyz;\n"
2805 " VectorR = gl_MultiTexCoord3.xyz;\n"
2808 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2809 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2811 "#ifdef USESHADOWMAPORTHO\n"
2812 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2815 "#ifdef USEREFLECTION\n"
2816 " ModelViewProjectionPosition = gl_Position;\n"
2819 "#endif // VERTEX_SHADER\n"
2824 "#ifdef FRAGMENT_SHADER\n"
2827 "#ifdef USEDEFERREDLIGHTMAP\n"
2829 "float2 Pixel : VPOS,\n"
2831 "float2 Pixel : WPOS,\n"
2834 "float4 gl_FrontColor : COLOR,\n"
2835 "float4 TexCoordBoth : TEXCOORD0,\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "float2 TexCoordLightmap : TEXCOORD1,\n"
2839 "#ifdef USEEYEVECTOR\n"
2840 "float3 EyeVector : TEXCOORD2,\n"
2842 "#ifdef USEREFLECTION\n"
2843 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2846 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2849 "float3 LightVector : TEXCOORD1,\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "float3 CubeVector : TEXCOORD3,\n"
2854 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2855 "float4 ModelViewPosition : TEXCOORD0,\n"
2857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2858 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2859 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2860 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2862 "#ifdef USESHADOWMAPORTHO\n"
2863 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2866 "uniform sampler Texture_Normal : register(s0),\n"
2867 "uniform sampler Texture_Color : register(s1),\n"
2868 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2869 "uniform sampler Texture_Gloss : register(s2),\n"
2872 "uniform sampler Texture_Glow : register(s3),\n"
2874 "#ifdef USEVERTEXTEXTUREBLEND\n"
2875 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2876 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2877 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2878 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2881 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2884 "#ifdef USECOLORMAPPING\n"
2885 "uniform sampler Texture_Pants : register(s4),\n"
2886 "uniform sampler Texture_Shirt : register(s7),\n"
2889 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2890 "uniform sampler Texture_FogMask : register(s8),\n"
2892 "#ifdef USELIGHTMAP\n"
2893 "uniform sampler Texture_Lightmap : register(s9),\n"
2895 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2896 "uniform sampler Texture_Deluxemap : register(s10),\n"
2898 "#ifdef USEREFLECTION\n"
2899 "uniform sampler Texture_Reflection : register(s7),\n"
2902 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2903 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2904 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2906 "#ifdef USEDEFERREDLIGHTMAP\n"
2907 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2908 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2911 "#ifdef USECOLORMAPPING\n"
2912 "uniform half3 Color_Pants : register(c7),\n"
2913 "uniform half3 Color_Shirt : register(c8),\n"
2916 "uniform float3 FogColor : register(c16),\n"
2917 "uniform float FogRangeRecip : register(c20),\n"
2918 "uniform float FogPlaneViewDist : register(c19),\n"
2919 "uniform float FogHeightFade : register(c17),\n"
2922 "#ifdef USEOFFSETMAPPING\n"
2923 "uniform float OffsetMapping_Scale : register(c24),\n"
2926 "#ifdef USEDEFERREDLIGHTMAP\n"
2927 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2928 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2929 "uniform half3 DeferredMod_Specular : register(c13),\n"
2931 "uniform half3 Color_Ambient : register(c3),\n"
2932 "uniform half3 Color_Diffuse : register(c4),\n"
2933 "uniform half3 Color_Specular : register(c5),\n"
2934 "uniform half SpecularPower : register(c36),\n"
2936 "uniform half3 Color_Glow : register(c6),\n"
2938 "uniform half Alpha : register(c0),\n"
2939 "#ifdef USEREFLECTION\n"
2940 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2941 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2942 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2943 "uniform half4 ReflectColor : register(c26),\n"
2945 "#ifdef USEREFLECTCUBE\n"
2946 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2947 "uniform sampler Texture_ReflectMask : register(s5),\n"
2948 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2950 "#ifdef MODE_LIGHTDIRECTION\n"
2951 "uniform half3 LightColor : register(c21),\n"
2953 "#ifdef MODE_LIGHTSOURCE\n"
2954 "uniform half3 LightColor : register(c21),\n"
2957 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2958 "uniform sampler Texture_Attenuation : register(s9),\n"
2959 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2962 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2964 "#ifdef USESHADOWMAP2D\n"
2965 "# ifdef USESHADOWSAMPLER\n"
2966 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2968 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2972 "#ifdef USESHADOWMAPVSDCT\n"
2973 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2976 "#if defined(USESHADOWMAP2D)\n"
2977 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2978 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2980 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2982 "out float4 gl_FragColor : COLOR\n"
2985 " float2 TexCoord = TexCoordBoth.xy;\n"
2986 "#ifdef USEVERTEXTEXTUREBLEND\n"
2987 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2989 "#ifdef USEOFFSETMAPPING\n"
2990 " // apply offsetmapping\n"
2991 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2992 "#define TexCoord TexCoordOffset\n"
2995 " // combine the diffuse textures (base, pants, shirt)\n"
2996 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2997 "#ifdef USEALPHAKILL\n"
2998 " if (color.a < 0.5)\n"
3001 " color.a *= Alpha;\n"
3002 "#ifdef USECOLORMAPPING\n"
3003 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3005 "#ifdef USEVERTEXTEXTUREBLEND\n"
3006 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3007 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3008 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3009 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3011 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3014 " // get the surface normal\n"
3015 "#ifdef USEVERTEXTEXTUREBLEND\n"
3016 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3018 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3021 " // get the material colors\n"
3022 " half3 diffusetex = color.rgb;\n"
3023 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3024 "# ifdef USEVERTEXTEXTUREBLEND\n"
3025 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3027 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3033 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3034 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3035 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3041 "#ifdef MODE_LIGHTSOURCE\n"
3042 " // light source\n"
3043 "#ifdef USEDIFFUSE\n"
3044 " half3 lightnormal = half3(normalize(LightVector));\n"
3045 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3046 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3047 "#ifdef USESPECULAR\n"
3048 "#ifdef USEEXACTSPECULARMATH\n"
3049 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3051 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3052 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3054 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3057 " color.rgb = diffusetex * Color_Ambient;\n"
3059 " color.rgb *= LightColor;\n"
3060 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3063 "#ifdef USESHADOWMAPVSDCT\n"
3064 ", Texture_CubeProjection\n"
3069 "# ifdef USECUBEFILTER\n"
3070 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3073 "#ifdef USESHADOWMAP2D\n"
3074 "#ifdef USESHADOWMAPVSDCT\n"
3075 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3076 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3077 "// color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3078 "// color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3080 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3081 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3082 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3083 "// color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3084 "// color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3085 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3086 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3087 "// color.r = half(shadowmaptc.z);\n"
3091 "// color.rgb = half3(1,1,1);\n"
3092 "#endif // MODE_LIGHTSOURCE\n"
3097 "#ifdef MODE_LIGHTDIRECTION\n"
3099 "#ifdef USEDIFFUSE\n"
3100 " half3 lightnormal = half3(normalize(LightVector));\n"
3102 "#define lightcolor LightColor\n"
3103 "#endif // MODE_LIGHTDIRECTION\n"
3104 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3106 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3107 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3108 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3109 " // convert modelspace light vector to tangentspace\n"
3110 " half3 lightnormal;\n"
3111 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3112 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3113 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3114 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3115 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3116 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3117 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3118 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3119 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3120 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3121 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3122 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3123 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3124 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3125 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3127 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3128 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3129 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3135 "#ifdef MODE_LIGHTMAP\n"
3136 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3137 "#endif // MODE_LIGHTMAP\n"
3138 "#ifdef MODE_VERTEXCOLOR\n"
3139 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3140 "#endif // MODE_VERTEXCOLOR\n"
3141 "#ifdef MODE_FLATCOLOR\n"
3142 " color.rgb = diffusetex * Color_Ambient;\n"
3143 "#endif // MODE_FLATCOLOR\n"
3149 "# ifdef USEDIFFUSE\n"
3150 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3151 "# ifdef USESPECULAR\n"
3152 "# ifdef USEEXACTSPECULARMATH\n"
3153 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3155 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3156 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3158 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3160 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3163 " color.rgb = diffusetex * Color_Ambient;\n"
3167 "#ifdef USESHADOWMAPORTHO\n"
3168 " color.rgb *= ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale);\n"
3171 "#ifdef USEDEFERREDLIGHTMAP\n"
3172 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3173 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3174 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3178 "#ifdef USEVERTEXTEXTUREBLEND\n"
3179 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3181 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3186 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3189 " // 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"
3190 "#ifdef USEREFLECTION\n"
3191 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3192 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3193 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3194 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3195 " // FIXME temporary hack to detect the case that the reflection\n"
3196 " // gets blackened at edges due to leaving the area that contains actual\n"
3198 " // Remove this 'ack once we have a better way to stop this thing from\n"
3200 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3201 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3202 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3203 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3204 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3205 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3208 " gl_FragColor = float4(color);\n"
3210 "#endif // FRAGMENT_SHADER\n"
3212 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3213 "#endif // !MODE_DEFERREDGEOMETRY\n"
3214 "#endif // !MODE_WATER\n"
3215 "#endif // !MODE_REFRACTION\n"
3216 "#endif // !MODE_BLOOMBLUR\n"
3217 "#endif // !MODE_GENERIC\n"
3218 "#endif // !MODE_POSTPROCESS\n"
3219 "#endif // !MODE_SHOWDEPTH\n"
3220 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3223 char *glslshaderstring = NULL;
3224 char *cgshaderstring = NULL;
3225 char *hlslshaderstring = NULL;
3227 //=======================================================================================================================================================
3229 typedef struct shaderpermutationinfo_s
3231 const char *pretext;
3234 shaderpermutationinfo_t;
3236 typedef struct shadermodeinfo_s
3238 const char *vertexfilename;
3239 const char *geometryfilename;
3240 const char *fragmentfilename;
3241 const char *pretext;
3246 typedef enum shaderpermutation_e
3248 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3249 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3250 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3251 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3252 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3253 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3254 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3255 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3256 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3257 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3258 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3259 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3260 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3261 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3262 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3263 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3264 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3265 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3266 SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3267 SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3268 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3269 SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3270 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3271 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3272 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3273 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3274 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3275 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3276 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3278 shaderpermutation_t;
3280 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3281 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3283 {"#define USEDIFFUSE\n", " diffuse"},
3284 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3285 {"#define USEVIEWTINT\n", " viewtint"},
3286 {"#define USECOLORMAPPING\n", " colormapping"},
3287 {"#define USESATURATION\n", " saturation"},
3288 {"#define USEFOGINSIDE\n", " foginside"},
3289 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3290 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3291 {"#define USEGAMMARAMPS\n", " gammaramps"},
3292 {"#define USECUBEFILTER\n", " cubefilter"},
3293 {"#define USEGLOW\n", " glow"},
3294 {"#define USEBLOOM\n", " bloom"},
3295 {"#define USESPECULAR\n", " specular"},
3296 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3297 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3298 {"#define USEREFLECTION\n", " reflection"},
3299 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3300 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3301 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3302 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3303 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3304 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3305 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3306 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3307 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3308 {"#define USEALPHAKILL\n", " alphakill"},
3309 {"#define USEREFLECTCUBE\n", " reflectcube"},
3312 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3313 typedef enum shadermode_e
3315 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3316 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3317 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3318 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3319 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3320 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3321 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3322 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3323 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3324 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3325 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3326 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3327 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3328 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3329 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3334 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3335 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3337 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3338 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3339 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3340 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3341 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3342 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3343 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3344 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3345 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3346 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3347 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3348 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3349 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3350 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3351 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3355 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3357 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3358 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3359 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3360 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3361 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3362 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3363 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3364 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3365 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3366 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3367 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3368 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3369 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3370 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3371 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3376 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3378 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3379 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3380 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3381 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3382 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3383 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3384 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3385 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3386 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3387 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3388 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3389 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3390 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3391 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3392 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3396 struct r_glsl_permutation_s;
3397 typedef struct r_glsl_permutation_s
3399 /// hash lookup data
3400 struct r_glsl_permutation_s *hashnext;
3402 unsigned int permutation;
3404 /// indicates if we have tried compiling this permutation already
3406 /// 0 if compilation failed
3408 /// locations of detected uniforms in program object, or -1 if not found
3409 int loc_Texture_First;
3410 int loc_Texture_Second;
3411 int loc_Texture_GammaRamps;
3412 int loc_Texture_Normal;
3413 int loc_Texture_Color;
3414 int loc_Texture_Gloss;
3415 int loc_Texture_Glow;
3416 int loc_Texture_SecondaryNormal;
3417 int loc_Texture_SecondaryColor;
3418 int loc_Texture_SecondaryGloss;
3419 int loc_Texture_SecondaryGlow;
3420 int loc_Texture_Pants;
3421 int loc_Texture_Shirt;
3422 int loc_Texture_FogHeightTexture;
3423 int loc_Texture_FogMask;
3424 int loc_Texture_Lightmap;
3425 int loc_Texture_Deluxemap;
3426 int loc_Texture_Attenuation;
3427 int loc_Texture_Cube;
3428 int loc_Texture_Refraction;
3429 int loc_Texture_Reflection;
3430 int loc_Texture_ShadowMap2D;
3431 int loc_Texture_CubeProjection;
3432 int loc_Texture_ScreenDepth;
3433 int loc_Texture_ScreenNormalMap;
3434 int loc_Texture_ScreenDiffuse;
3435 int loc_Texture_ScreenSpecular;
3436 int loc_Texture_ReflectMask;
3437 int loc_Texture_ReflectCube;
3439 int loc_BloomBlur_Parameters;
3441 int loc_Color_Ambient;
3442 int loc_Color_Diffuse;
3443 int loc_Color_Specular;
3445 int loc_Color_Pants;
3446 int loc_Color_Shirt;
3447 int loc_DeferredColor_Ambient;
3448 int loc_DeferredColor_Diffuse;
3449 int loc_DeferredColor_Specular;
3450 int loc_DeferredMod_Diffuse;
3451 int loc_DeferredMod_Specular;
3452 int loc_DistortScaleRefractReflect;
3453 int loc_EyePosition;
3455 int loc_FogHeightFade;
3457 int loc_FogPlaneViewDist;
3458 int loc_FogRangeRecip;
3461 int loc_LightPosition;
3462 int loc_OffsetMapping_Scale;
3464 int loc_ReflectColor;
3465 int loc_ReflectFactor;
3466 int loc_ReflectOffset;
3467 int loc_RefractColor;
3469 int loc_ScreenCenterRefractReflect;
3470 int loc_ScreenScaleRefractReflect;
3471 int loc_ScreenToDepth;
3472 int loc_ShadowMap_Parameters;
3473 int loc_ShadowMap_TextureScale;
3474 int loc_SpecularPower;
3479 int loc_ViewTintColor;
3480 int loc_ViewToLight;
3481 int loc_ModelToLight;
3483 int loc_BackgroundTexMatrix;
3484 int loc_ModelViewProjectionMatrix;
3485 int loc_ModelViewMatrix;
3486 int loc_PixelToScreenTexCoord;
3487 int loc_ModelToReflectCube;
3488 int loc_ShadowMapMatrix;
3489 int loc_BloomColorSubtract;
3491 r_glsl_permutation_t;
3493 #define SHADERPERMUTATION_HASHSIZE 256
3495 /// information about each possible shader permutation
3496 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3497 /// currently selected permutation
3498 r_glsl_permutation_t *r_glsl_permutation;
3499 /// storage for permutations linked in the hash table
3500 memexpandablearray_t r_glsl_permutationarray;
3502 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3504 //unsigned int hashdepth = 0;
3505 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3506 r_glsl_permutation_t *p;
3507 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3509 if (p->mode == mode && p->permutation == permutation)
3511 //if (hashdepth > 10)
3512 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3517 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3519 p->permutation = permutation;
3520 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3521 r_glsl_permutationhash[mode][hashindex] = p;
3522 //if (hashdepth > 10)
3523 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3527 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3530 if (!filename || !filename[0])
3532 if (!strcmp(filename, "glsl/default.glsl"))
3534 if (!glslshaderstring)
3536 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3537 if (glslshaderstring)
3538 Con_DPrintf("Loading shaders from file %s...\n", filename);
3540 glslshaderstring = (char *)builtinshaderstring;
3542 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3543 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3544 return shaderstring;
3546 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3549 if (printfromdisknotice)
3550 Con_DPrintf("from disk %s... ", filename);
3551 return shaderstring;
3553 return shaderstring;
3556 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3559 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3560 int vertstrings_count = 0;
3561 int geomstrings_count = 0;
3562 int fragstrings_count = 0;
3563 char *vertexstring, *geometrystring, *fragmentstring;
3564 const char *vertstrings_list[32+3];
3565 const char *geomstrings_list[32+3];
3566 const char *fragstrings_list[32+3];
3567 char permutationname[256];
3574 permutationname[0] = 0;
3575 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3576 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3577 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3579 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3581 // the first pretext is which type of shader to compile as
3582 // (later these will all be bound together as a program object)
3583 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3584 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3585 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3587 // the second pretext is the mode (for example a light source)
3588 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3589 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3590 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3591 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3593 // now add all the permutation pretexts
3594 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3596 if (permutation & (1<<i))
3598 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3599 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3600 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3601 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3605 // keep line numbers correct
3606 vertstrings_list[vertstrings_count++] = "\n";
3607 geomstrings_list[geomstrings_count++] = "\n";
3608 fragstrings_list[fragstrings_count++] = "\n";
3612 // now append the shader text itself
3613 vertstrings_list[vertstrings_count++] = vertexstring;
3614 geomstrings_list[geomstrings_count++] = geometrystring;
3615 fragstrings_list[fragstrings_count++] = fragmentstring;
3617 // if any sources were NULL, clear the respective list
3619 vertstrings_count = 0;
3620 if (!geometrystring)
3621 geomstrings_count = 0;
3622 if (!fragmentstring)
3623 fragstrings_count = 0;
3625 // compile the shader program
3626 if (vertstrings_count + geomstrings_count + fragstrings_count)
3627 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3631 qglUseProgramObjectARB(p->program);CHECKGLERROR
3632 // look up all the uniform variable names we care about, so we don't
3633 // have to look them up every time we set them
3635 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3636 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3637 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3638 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3639 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3640 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3641 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3642 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3643 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3644 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3645 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3646 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3647 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3648 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3649 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3650 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3651 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3652 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3653 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3654 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3655 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3656 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3657 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3658 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3659 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3660 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3661 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3662 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3663 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3664 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3665 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3666 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3667 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3668 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3669 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3670 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3671 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3672 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3673 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3674 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3675 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3676 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3677 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3678 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3679 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3680 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3681 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3682 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3683 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3684 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3685 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3686 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3687 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3688 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3689 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3690 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3691 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3692 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3693 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3694 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3695 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3696 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3697 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3698 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3699 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3700 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3701 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3702 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3703 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3704 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3705 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3706 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3707 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3708 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3709 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3710 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3711 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3712 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3713 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3714 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3715 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3716 // initialize the samplers to refer to the texture units we use
3717 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3718 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3719 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3720 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3721 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3722 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3723 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3724 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3725 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3726 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3727 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3728 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3729 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3730 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3731 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3732 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3733 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3734 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3735 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3736 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3737 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3738 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3739 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3740 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3741 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3742 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3743 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3744 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3745 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3747 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3750 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3754 Mem_Free(vertexstring);
3756 Mem_Free(geometrystring);
3758 Mem_Free(fragmentstring);
3761 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3763 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3764 if (r_glsl_permutation != perm)
3766 r_glsl_permutation = perm;
3767 if (!r_glsl_permutation->program)
3769 if (!r_glsl_permutation->compiled)
3770 R_GLSL_CompilePermutation(perm, mode, permutation);
3771 if (!r_glsl_permutation->program)
3773 // remove features until we find a valid permutation
3775 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3777 // reduce i more quickly whenever it would not remove any bits
3778 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3779 if (!(permutation & j))
3782 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3783 if (!r_glsl_permutation->compiled)
3784 R_GLSL_CompilePermutation(perm, mode, permutation);
3785 if (r_glsl_permutation->program)
3788 if (i >= SHADERPERMUTATION_COUNT)
3790 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3791 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3792 qglUseProgramObjectARB(0);CHECKGLERROR
3793 return; // no bit left to clear, entire mode is broken
3798 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3800 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3801 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3802 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3806 #include <Cg/cgGL.h>
3807 struct r_cg_permutation_s;
3808 typedef struct r_cg_permutation_s
3810 /// hash lookup data
3811 struct r_cg_permutation_s *hashnext;
3813 unsigned int permutation;
3815 /// indicates if we have tried compiling this permutation already
3817 /// 0 if compilation failed
3820 /// locations of detected parameters in programs, or NULL if not found
3821 CGparameter vp_EyePosition;
3822 CGparameter vp_FogPlane;
3823 CGparameter vp_LightDir;
3824 CGparameter vp_LightPosition;
3825 CGparameter vp_ModelToLight;
3826 CGparameter vp_TexMatrix;
3827 CGparameter vp_BackgroundTexMatrix;
3828 CGparameter vp_ModelViewProjectionMatrix;
3829 CGparameter vp_ModelViewMatrix;
3830 CGparameter vp_ShadowMapMatrix;
3832 CGparameter fp_Texture_First;
3833 CGparameter fp_Texture_Second;
3834 CGparameter fp_Texture_GammaRamps;
3835 CGparameter fp_Texture_Normal;
3836 CGparameter fp_Texture_Color;
3837 CGparameter fp_Texture_Gloss;
3838 CGparameter fp_Texture_Glow;
3839 CGparameter fp_Texture_SecondaryNormal;
3840 CGparameter fp_Texture_SecondaryColor;
3841 CGparameter fp_Texture_SecondaryGloss;
3842 CGparameter fp_Texture_SecondaryGlow;
3843 CGparameter fp_Texture_Pants;
3844 CGparameter fp_Texture_Shirt;
3845 CGparameter fp_Texture_FogHeightTexture;
3846 CGparameter fp_Texture_FogMask;
3847 CGparameter fp_Texture_Lightmap;
3848 CGparameter fp_Texture_Deluxemap;
3849 CGparameter fp_Texture_Attenuation;
3850 CGparameter fp_Texture_Cube;
3851 CGparameter fp_Texture_Refraction;
3852 CGparameter fp_Texture_Reflection;
3853 CGparameter fp_Texture_ShadowMap2D;
3854 CGparameter fp_Texture_CubeProjection;
3855 CGparameter fp_Texture_ScreenDepth;
3856 CGparameter fp_Texture_ScreenNormalMap;
3857 CGparameter fp_Texture_ScreenDiffuse;
3858 CGparameter fp_Texture_ScreenSpecular;
3859 CGparameter fp_Texture_ReflectMask;
3860 CGparameter fp_Texture_ReflectCube;
3861 CGparameter fp_Alpha;
3862 CGparameter fp_BloomBlur_Parameters;
3863 CGparameter fp_ClientTime;
3864 CGparameter fp_Color_Ambient;
3865 CGparameter fp_Color_Diffuse;
3866 CGparameter fp_Color_Specular;
3867 CGparameter fp_Color_Glow;
3868 CGparameter fp_Color_Pants;
3869 CGparameter fp_Color_Shirt;
3870 CGparameter fp_DeferredColor_Ambient;
3871 CGparameter fp_DeferredColor_Diffuse;
3872 CGparameter fp_DeferredColor_Specular;
3873 CGparameter fp_DeferredMod_Diffuse;
3874 CGparameter fp_DeferredMod_Specular;
3875 CGparameter fp_DistortScaleRefractReflect;
3876 CGparameter fp_EyePosition;
3877 CGparameter fp_FogColor;
3878 CGparameter fp_FogHeightFade;
3879 CGparameter fp_FogPlane;
3880 CGparameter fp_FogPlaneViewDist;
3881 CGparameter fp_FogRangeRecip;
3882 CGparameter fp_LightColor;
3883 CGparameter fp_LightDir;
3884 CGparameter fp_LightPosition;
3885 CGparameter fp_OffsetMapping_Scale;
3886 CGparameter fp_PixelSize;
3887 CGparameter fp_ReflectColor;
3888 CGparameter fp_ReflectFactor;
3889 CGparameter fp_ReflectOffset;
3890 CGparameter fp_RefractColor;
3891 CGparameter fp_Saturation;
3892 CGparameter fp_ScreenCenterRefractReflect;
3893 CGparameter fp_ScreenScaleRefractReflect;
3894 CGparameter fp_ScreenToDepth;
3895 CGparameter fp_ShadowMap_Parameters;
3896 CGparameter fp_ShadowMap_TextureScale;
3897 CGparameter fp_SpecularPower;
3898 CGparameter fp_UserVec1;
3899 CGparameter fp_UserVec2;
3900 CGparameter fp_UserVec3;
3901 CGparameter fp_UserVec4;
3902 CGparameter fp_ViewTintColor;
3903 CGparameter fp_ViewToLight;
3904 CGparameter fp_PixelToScreenTexCoord;
3905 CGparameter fp_ModelToReflectCube;
3906 CGparameter fp_BloomColorSubtract;
3910 /// information about each possible shader permutation
3911 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3912 /// currently selected permutation
3913 r_cg_permutation_t *r_cg_permutation;
3914 /// storage for permutations linked in the hash table
3915 memexpandablearray_t r_cg_permutationarray;
3917 #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));}}
3919 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3921 //unsigned int hashdepth = 0;
3922 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3923 r_cg_permutation_t *p;
3924 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3926 if (p->mode == mode && p->permutation == permutation)
3928 //if (hashdepth > 10)
3929 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3934 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3936 p->permutation = permutation;
3937 p->hashnext = r_cg_permutationhash[mode][hashindex];
3938 r_cg_permutationhash[mode][hashindex] = p;
3939 //if (hashdepth > 10)
3940 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3944 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3947 if (!filename || !filename[0])
3949 if (!strcmp(filename, "cg/default.cg"))
3951 if (!cgshaderstring)
3953 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3955 Con_DPrintf("Loading shaders from file %s...\n", filename);
3957 cgshaderstring = (char *)builtincgshaderstring;
3959 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3960 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3961 return shaderstring;
3963 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3966 if (printfromdisknotice)
3967 Con_DPrintf("from disk %s... ", filename);
3968 return shaderstring;
3970 return shaderstring;
3973 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3975 // TODO: load or create .fp and .vp shader files
3978 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3981 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3982 int vertstrings_count = 0, vertstring_length = 0;
3983 int geomstrings_count = 0, geomstring_length = 0;
3984 int fragstrings_count = 0, fragstring_length = 0;
3986 char *vertexstring, *geometrystring, *fragmentstring;
3987 char *vertstring, *geomstring, *fragstring;
3988 const char *vertstrings_list[32+3];
3989 const char *geomstrings_list[32+3];
3990 const char *fragstrings_list[32+3];
3991 char permutationname[256];
3992 char cachename[256];
3993 CGprofile vertexProfile;
3994 CGprofile fragmentProfile;
4002 permutationname[0] = 0;
4004 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4005 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4006 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4008 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4009 strlcat(cachename, "cg/", sizeof(cachename));
4011 // the first pretext is which type of shader to compile as
4012 // (later these will all be bound together as a program object)
4013 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4014 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4015 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4017 // the second pretext is the mode (for example a light source)
4018 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4019 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4020 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4021 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4022 strlcat(cachename, modeinfo->name, sizeof(cachename));
4024 // now add all the permutation pretexts
4025 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4027 if (permutation & (1<<i))
4029 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4030 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4031 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4032 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4033 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4037 // keep line numbers correct
4038 vertstrings_list[vertstrings_count++] = "\n";
4039 geomstrings_list[geomstrings_count++] = "\n";
4040 fragstrings_list[fragstrings_count++] = "\n";
4044 // replace spaces in the cachename with _ characters
4045 for (i = 0;cachename[i];i++)
4046 if (cachename[i] == ' ')
4049 // now append the shader text itself
4050 vertstrings_list[vertstrings_count++] = vertexstring;
4051 geomstrings_list[geomstrings_count++] = geometrystring;
4052 fragstrings_list[fragstrings_count++] = fragmentstring;
4054 // if any sources were NULL, clear the respective list
4056 vertstrings_count = 0;
4057 if (!geometrystring)
4058 geomstrings_count = 0;
4059 if (!fragmentstring)
4060 fragstrings_count = 0;
4062 vertstring_length = 0;
4063 for (i = 0;i < vertstrings_count;i++)
4064 vertstring_length += strlen(vertstrings_list[i]);
4065 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4066 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4067 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4069 geomstring_length = 0;
4070 for (i = 0;i < geomstrings_count;i++)
4071 geomstring_length += strlen(geomstrings_list[i]);
4072 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4073 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4074 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4076 fragstring_length = 0;
4077 for (i = 0;i < fragstrings_count;i++)
4078 fragstring_length += strlen(fragstrings_list[i]);
4079 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4080 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4081 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4085 //vertexProfile = CG_PROFILE_ARBVP1;
4086 //fragmentProfile = CG_PROFILE_ARBFP1;
4087 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4088 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4089 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4090 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4091 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4094 // try to load the cached shader, or generate one
4095 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4097 // if caching failed, do a dynamic compile for now
4099 if (vertstring[0] && !p->vprogram)
4100 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4102 if (fragstring[0] && !p->fprogram)
4103 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4106 // look up all the uniform variable names we care about, so we don't
4107 // have to look them up every time we set them
4111 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4112 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4113 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4114 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4115 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4116 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4117 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4118 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4119 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4120 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4121 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4122 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4128 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4129 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4130 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4131 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4132 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4133 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4134 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4135 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4136 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4137 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4138 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4139 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4140 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4141 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4142 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4143 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4144 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4145 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4146 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4147 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4148 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4149 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4150 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4151 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4152 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4153 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4154 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4155 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4156 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4157 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4158 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4159 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4160 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4161 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4162 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4163 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4164 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4165 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4166 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4167 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4168 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4169 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4170 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4171 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4172 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4173 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4174 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4175 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4176 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4177 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4178 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4179 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4180 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4181 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4182 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4183 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4184 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4185 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4186 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4187 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4188 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4189 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4190 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4191 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4192 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4193 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4194 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4195 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4196 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4197 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4198 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4199 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4200 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4201 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4202 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4203 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4204 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4208 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4209 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4211 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4215 Mem_Free(vertstring);
4217 Mem_Free(geomstring);
4219 Mem_Free(fragstring);
4221 Mem_Free(vertexstring);
4223 Mem_Free(geometrystring);
4225 Mem_Free(fragmentstring);
4228 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4230 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4233 if (r_cg_permutation != perm)
4235 r_cg_permutation = perm;
4236 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4238 if (!r_cg_permutation->compiled)
4239 R_CG_CompilePermutation(perm, mode, permutation);
4240 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4242 // remove features until we find a valid permutation
4244 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4246 // reduce i more quickly whenever it would not remove any bits
4247 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4248 if (!(permutation & j))
4251 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4252 if (!r_cg_permutation->compiled)
4253 R_CG_CompilePermutation(perm, mode, permutation);
4254 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4257 if (i >= SHADERPERMUTATION_COUNT)
4259 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4260 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4261 return; // no bit left to clear, entire mode is broken
4267 if (r_cg_permutation->vprogram)
4269 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4270 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4271 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4275 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4276 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4278 if (r_cg_permutation->fprogram)
4280 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4281 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4282 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4286 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4287 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4291 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4292 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4293 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4296 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4298 cgGLSetTextureParameter(param, R_GetTexture(tex));
4299 cgGLEnableTextureParameter(param);
4307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4308 extern D3DCAPS9 vid_d3d9caps;
4311 struct r_hlsl_permutation_s;
4312 typedef struct r_hlsl_permutation_s
4314 /// hash lookup data
4315 struct r_hlsl_permutation_s *hashnext;
4317 unsigned int permutation;
4319 /// indicates if we have tried compiling this permutation already
4321 /// NULL if compilation failed
4322 IDirect3DVertexShader9 *vertexshader;
4323 IDirect3DPixelShader9 *pixelshader;
4325 r_hlsl_permutation_t;
4327 typedef enum D3DVSREGISTER_e
4329 D3DVSREGISTER_TexMatrix = 0, // float4x4
4330 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4331 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4332 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4333 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4334 D3DVSREGISTER_ModelToLight = 20, // float4x4
4335 D3DVSREGISTER_EyePosition = 24,
4336 D3DVSREGISTER_FogPlane = 25,
4337 D3DVSREGISTER_LightDir = 26,
4338 D3DVSREGISTER_LightPosition = 27,
4342 typedef enum D3DPSREGISTER_e
4344 D3DPSREGISTER_Alpha = 0,
4345 D3DPSREGISTER_BloomBlur_Parameters = 1,
4346 D3DPSREGISTER_ClientTime = 2,
4347 D3DPSREGISTER_Color_Ambient = 3,
4348 D3DPSREGISTER_Color_Diffuse = 4,
4349 D3DPSREGISTER_Color_Specular = 5,
4350 D3DPSREGISTER_Color_Glow = 6,
4351 D3DPSREGISTER_Color_Pants = 7,
4352 D3DPSREGISTER_Color_Shirt = 8,
4353 D3DPSREGISTER_DeferredColor_Ambient = 9,
4354 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4355 D3DPSREGISTER_DeferredColor_Specular = 11,
4356 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4357 D3DPSREGISTER_DeferredMod_Specular = 13,
4358 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4359 D3DPSREGISTER_EyePosition = 15, // unused
4360 D3DPSREGISTER_FogColor = 16,
4361 D3DPSREGISTER_FogHeightFade = 17,
4362 D3DPSREGISTER_FogPlane = 18,
4363 D3DPSREGISTER_FogPlaneViewDist = 19,
4364 D3DPSREGISTER_FogRangeRecip = 20,
4365 D3DPSREGISTER_LightColor = 21,
4366 D3DPSREGISTER_LightDir = 22, // unused
4367 D3DPSREGISTER_LightPosition = 23,
4368 D3DPSREGISTER_OffsetMapping_Scale = 24,
4369 D3DPSREGISTER_PixelSize = 25,
4370 D3DPSREGISTER_ReflectColor = 26,
4371 D3DPSREGISTER_ReflectFactor = 27,
4372 D3DPSREGISTER_ReflectOffset = 28,
4373 D3DPSREGISTER_RefractColor = 29,
4374 D3DPSREGISTER_Saturation = 30,
4375 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4376 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4377 D3DPSREGISTER_ScreenToDepth = 33,
4378 D3DPSREGISTER_ShadowMap_Parameters = 34,
4379 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4380 D3DPSREGISTER_SpecularPower = 36,
4381 D3DPSREGISTER_UserVec1 = 37,
4382 D3DPSREGISTER_UserVec2 = 38,
4383 D3DPSREGISTER_UserVec3 = 39,
4384 D3DPSREGISTER_UserVec4 = 40,
4385 D3DPSREGISTER_ViewTintColor = 41,
4386 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4387 D3DPSREGISTER_BloomColorSubtract = 43,
4388 D3DPSREGISTER_ViewToLight = 44, // float4x4
4389 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4394 /// information about each possible shader permutation
4395 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4396 /// currently selected permutation
4397 r_hlsl_permutation_t *r_hlsl_permutation;
4398 /// storage for permutations linked in the hash table
4399 memexpandablearray_t r_hlsl_permutationarray;
4401 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4403 //unsigned int hashdepth = 0;
4404 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4405 r_hlsl_permutation_t *p;
4406 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4408 if (p->mode == mode && p->permutation == permutation)
4410 //if (hashdepth > 10)
4411 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4416 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4418 p->permutation = permutation;
4419 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4420 r_hlsl_permutationhash[mode][hashindex] = p;
4421 //if (hashdepth > 10)
4422 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4426 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4429 if (!filename || !filename[0])
4431 if (!strcmp(filename, "hlsl/default.hlsl"))
4433 if (!hlslshaderstring)
4435 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4436 if (hlslshaderstring)
4437 Con_DPrintf("Loading shaders from file %s...\n", filename);
4439 hlslshaderstring = (char *)builtincgshaderstring;
4441 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4442 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4443 return shaderstring;
4445 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4448 if (printfromdisknotice)
4449 Con_DPrintf("from disk %s... ", filename);
4450 return shaderstring;
4452 return shaderstring;
4456 //#include <d3dx9shader.h>
4457 //#include <d3dx9mesh.h>
4459 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4461 DWORD *vsbin = NULL;
4462 DWORD *psbin = NULL;
4463 fs_offset_t vsbinsize;
4464 fs_offset_t psbinsize;
4465 // IDirect3DVertexShader9 *vs = NULL;
4466 // IDirect3DPixelShader9 *ps = NULL;
4467 ID3DXBuffer *vslog = NULL;
4468 ID3DXBuffer *vsbuffer = NULL;
4469 ID3DXConstantTable *vsconstanttable = NULL;
4470 ID3DXBuffer *pslog = NULL;
4471 ID3DXBuffer *psbuffer = NULL;
4472 ID3DXConstantTable *psconstanttable = NULL;
4475 char temp[MAX_INPUTLINE];
4476 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4477 qboolean debugshader = gl_paranoid.integer != 0;
4478 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4479 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4482 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4483 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4485 if (debugshader || (!vsbin && vertstring) || (!psbin && fragstring))
4487 const char* dllnames_d3dx9 [] =
4511 dllhandle_t d3dx9_dll = NULL;
4512 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4513 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4514 dllfunction_t d3dx9_dllfuncs[] =
4516 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4517 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4520 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4522 DWORD shaderflags = 0;
4524 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4525 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4526 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4527 if (vertstring && vertstring[0])
4531 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4532 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4535 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4538 vsbinsize = vsbuffer->GetBufferSize();
4539 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4540 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4541 vsbuffer->Release();
4545 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4546 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4550 if (fragstring && fragstring[0])
4554 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4555 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4558 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4561 psbinsize = psbuffer->GetBufferSize();
4562 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4563 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4564 psbuffer->Release();
4568 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4569 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4573 Sys_UnloadLibrary(&d3dx9_dll);
4576 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4580 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4581 if (FAILED(vsresult))
4582 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4586 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4587 if (FAILED(psresult))
4588 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4590 // free the shader data
4591 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4592 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4595 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4598 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4599 int vertstrings_count = 0, vertstring_length = 0;
4600 int geomstrings_count = 0, geomstring_length = 0;
4601 int fragstrings_count = 0, fragstring_length = 0;
4603 char *vertexstring, *geometrystring, *fragmentstring;
4604 char *vertstring, *geomstring, *fragstring;
4605 const char *vertstrings_list[32+3];
4606 const char *geomstrings_list[32+3];
4607 const char *fragstrings_list[32+3];
4608 char permutationname[256];
4609 char cachename[256];
4614 p->vertexshader = NULL;
4615 p->pixelshader = NULL;
4617 permutationname[0] = 0;
4619 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4620 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4621 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4623 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4624 strlcat(cachename, "hlsl/", sizeof(cachename));
4626 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4627 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4628 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4629 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4631 // the first pretext is which type of shader to compile as
4632 // (later these will all be bound together as a program object)
4633 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4634 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4635 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4637 // the second pretext is the mode (for example a light source)
4638 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4639 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4640 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4641 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4642 strlcat(cachename, modeinfo->name, sizeof(cachename));
4644 // now add all the permutation pretexts
4645 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4647 if (permutation & (1<<i))
4649 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4650 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4651 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4652 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4653 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4657 // keep line numbers correct
4658 vertstrings_list[vertstrings_count++] = "\n";
4659 geomstrings_list[geomstrings_count++] = "\n";
4660 fragstrings_list[fragstrings_count++] = "\n";
4664 // replace spaces in the cachename with _ characters
4665 for (i = 0;cachename[i];i++)
4666 if (cachename[i] == ' ')
4669 // now append the shader text itself
4670 vertstrings_list[vertstrings_count++] = vertexstring;
4671 geomstrings_list[geomstrings_count++] = geometrystring;
4672 fragstrings_list[fragstrings_count++] = fragmentstring;
4674 // if any sources were NULL, clear the respective list
4676 vertstrings_count = 0;
4677 if (!geometrystring)
4678 geomstrings_count = 0;
4679 if (!fragmentstring)
4680 fragstrings_count = 0;
4682 vertstring_length = 0;
4683 for (i = 0;i < vertstrings_count;i++)
4684 vertstring_length += strlen(vertstrings_list[i]);
4685 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4686 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4687 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4689 geomstring_length = 0;
4690 for (i = 0;i < geomstrings_count;i++)
4691 geomstring_length += strlen(geomstrings_list[i]);
4692 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4693 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4694 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4696 fragstring_length = 0;
4697 for (i = 0;i < fragstrings_count;i++)
4698 fragstring_length += strlen(fragstrings_list[i]);
4699 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4700 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4701 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4703 // try to load the cached shader, or generate one
4704 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4706 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4707 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4709 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4713 Mem_Free(vertstring);
4715 Mem_Free(geomstring);
4717 Mem_Free(fragstring);
4719 Mem_Free(vertexstring);
4721 Mem_Free(geometrystring);
4723 Mem_Free(fragmentstring);
4726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4728 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4729 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4730 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4731 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4735 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4736 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4737 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4738 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4742 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4743 if (r_hlsl_permutation != perm)
4745 r_hlsl_permutation = perm;
4746 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4748 if (!r_hlsl_permutation->compiled)
4749 R_HLSL_CompilePermutation(perm, mode, permutation);
4750 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4752 // remove features until we find a valid permutation
4754 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4756 // reduce i more quickly whenever it would not remove any bits
4757 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4758 if (!(permutation & j))
4761 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4762 if (!r_hlsl_permutation->compiled)
4763 R_HLSL_CompilePermutation(perm, mode, permutation);
4764 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4767 if (i >= SHADERPERMUTATION_COUNT)
4769 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4770 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4771 return; // no bit left to clear, entire mode is broken
4775 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4776 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4778 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4779 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4780 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4784 void R_GLSL_Restart_f(void)
4786 unsigned int i, limit;
4787 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4788 Mem_Free(glslshaderstring);
4789 glslshaderstring = NULL;
4790 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4791 Mem_Free(cgshaderstring);
4792 cgshaderstring = NULL;
4793 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4794 Mem_Free(hlslshaderstring);
4795 hlslshaderstring = NULL;
4796 switch(vid.renderpath)
4798 case RENDERPATH_D3D9:
4801 r_hlsl_permutation_t *p;
4802 r_hlsl_permutation = NULL;
4803 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4804 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4805 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4806 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4807 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4808 for (i = 0;i < limit;i++)
4810 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4812 if (p->vertexshader)
4813 IDirect3DVertexShader9_Release(p->vertexshader);
4815 IDirect3DPixelShader9_Release(p->pixelshader);
4816 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4819 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4823 case RENDERPATH_D3D10:
4824 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4826 case RENDERPATH_D3D11:
4827 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4829 case RENDERPATH_GL20:
4831 r_glsl_permutation_t *p;
4832 r_glsl_permutation = NULL;
4833 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4834 for (i = 0;i < limit;i++)
4836 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4838 GL_Backend_FreeProgram(p->program);
4839 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4842 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4845 case RENDERPATH_CGGL:
4848 r_cg_permutation_t *p;
4849 r_cg_permutation = NULL;
4850 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4851 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4852 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4853 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4854 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4855 for (i = 0;i < limit;i++)
4857 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4860 cgDestroyProgram(p->vprogram);
4862 cgDestroyProgram(p->fprogram);
4863 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4866 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4870 case RENDERPATH_GL13:
4871 case RENDERPATH_GL11:
4876 void R_GLSL_DumpShader_f(void)
4881 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4884 FS_Print(file, "/* The engine may define the following macros:\n");
4885 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4886 for (i = 0;i < SHADERMODE_COUNT;i++)
4887 FS_Print(file, glslshadermodeinfo[i].pretext);
4888 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4889 FS_Print(file, shaderpermutationinfo[i].pretext);
4890 FS_Print(file, "*/\n");
4891 FS_Print(file, builtinshaderstring);
4893 Con_Printf("glsl/default.glsl written\n");
4896 Con_Printf("failed to write to glsl/default.glsl\n");
4899 file = FS_OpenRealFile("cg/default.cg", "w", false);
4902 FS_Print(file, "/* The engine may define the following macros:\n");
4903 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4904 for (i = 0;i < SHADERMODE_COUNT;i++)
4905 FS_Print(file, cgshadermodeinfo[i].pretext);
4906 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4907 FS_Print(file, shaderpermutationinfo[i].pretext);
4908 FS_Print(file, "*/\n");
4909 FS_Print(file, builtincgshaderstring);
4911 Con_Printf("cg/default.cg written\n");
4914 Con_Printf("failed to write to cg/default.cg\n");
4918 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4921 FS_Print(file, "/* The engine may define the following macros:\n");
4922 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4923 for (i = 0;i < SHADERMODE_COUNT;i++)
4924 FS_Print(file, hlslshadermodeinfo[i].pretext);
4925 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4926 FS_Print(file, shaderpermutationinfo[i].pretext);
4927 FS_Print(file, "*/\n");
4928 FS_Print(file, builtincgshaderstring);
4930 Con_Printf("hlsl/default.hlsl written\n");
4933 Con_Printf("failed to write to hlsl/default.hlsl\n");
4937 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4940 texturemode = GL_MODULATE;
4941 switch (vid.renderpath)
4943 case RENDERPATH_D3D9:
4945 R_SetupShader_SetPermutationHLSL(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))));
4946 R_Mesh_TexBind(GL20TU_FIRST , first );
4947 R_Mesh_TexBind(GL20TU_SECOND, second);
4950 case RENDERPATH_D3D10:
4951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4953 case RENDERPATH_D3D11:
4954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4956 case RENDERPATH_GL20:
4957 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))));
4958 R_Mesh_TexBind(GL20TU_FIRST , first );
4959 R_Mesh_TexBind(GL20TU_SECOND, second);
4961 case RENDERPATH_CGGL:
4964 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))));
4965 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4966 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4969 case RENDERPATH_GL13:
4970 R_Mesh_TexBind(0, first );
4971 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4972 R_Mesh_TexBind(1, second);
4974 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4976 case RENDERPATH_GL11:
4977 R_Mesh_TexBind(0, first );
4982 void R_SetupShader_DepthOrShadow(void)
4984 switch (vid.renderpath)
4986 case RENDERPATH_D3D9:
4988 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4991 case RENDERPATH_D3D10:
4992 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4994 case RENDERPATH_D3D11:
4995 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4997 case RENDERPATH_GL20:
4998 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5000 case RENDERPATH_CGGL:
5002 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5005 case RENDERPATH_GL13:
5006 R_Mesh_TexBind(0, 0);
5007 R_Mesh_TexBind(1, 0);
5009 case RENDERPATH_GL11:
5010 R_Mesh_TexBind(0, 0);
5015 void R_SetupShader_ShowDepth(void)
5017 switch (vid.renderpath)
5019 case RENDERPATH_D3D9:
5021 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5024 case RENDERPATH_D3D10:
5025 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5027 case RENDERPATH_D3D11:
5028 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5030 case RENDERPATH_GL20:
5031 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5033 case RENDERPATH_CGGL:
5035 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5038 case RENDERPATH_GL13:
5040 case RENDERPATH_GL11:
5045 extern qboolean r_shadow_usingdeferredprepass;
5046 extern cvar_t r_shadow_deferred_8bitrange;
5047 extern rtexture_t *r_shadow_attenuationgradienttexture;
5048 extern rtexture_t *r_shadow_attenuation2dtexture;
5049 extern rtexture_t *r_shadow_attenuation3dtexture;
5050 extern qboolean r_shadow_usingshadowmap2d;
5051 extern qboolean r_shadow_usingshadowmaportho;
5052 extern float r_shadow_shadowmap_texturescale[2];
5053 extern float r_shadow_shadowmap_parameters[4];
5054 extern qboolean r_shadow_shadowmapvsdct;
5055 extern qboolean r_shadow_shadowmapsampler;
5056 extern int r_shadow_shadowmappcf;
5057 extern rtexture_t *r_shadow_shadowmap2dtexture;
5058 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5059 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5060 extern matrix4x4_t r_shadow_shadowmapmatrix;
5061 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5062 extern int r_shadow_prepass_width;
5063 extern int r_shadow_prepass_height;
5064 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5065 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5066 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5067 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5068 extern cvar_t gl_mesh_separatearrays;
5069 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5071 // a blendfunc allows colormod if:
5072 // a) it can never keep the destination pixel invariant, or
5073 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5074 // this is to prevent unintended side effects from colormod
5077 // IF there is a (s, sa) for which for all (d, da),
5078 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5079 // THEN, for this (s, sa) and all (colormod, d, da):
5080 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5081 // OBVIOUSLY, this means that
5082 // s*colormod * src(s*colormod, d, sa, da) = 0
5083 // dst(s*colormod, d, sa, da) = 1
5085 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5087 // main condition to leave dst color invariant:
5088 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5090 // s * 0 + d * dst(s, d, sa, da) == d
5091 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5092 // => colormod is a problem for GL_SRC_COLOR only
5094 // s + d * dst(s, d, sa, da) == d
5096 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5097 // => colormod is never problematic for these
5098 // src == GL_SRC_COLOR:
5099 // s*s + d * dst(s, d, sa, da) == d
5101 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5102 // => colormod is never problematic for these
5103 // src == GL_ONE_MINUS_SRC_COLOR:
5104 // s*(1-s) + d * dst(s, d, sa, da) == d
5105 // => s == 0 or s == 1
5106 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5107 // => colormod is a problem for GL_SRC_COLOR only
5108 // src == GL_DST_COLOR
5109 // s*d + d * dst(s, d, sa, da) == d
5111 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5112 // => colormod is always a problem
5115 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5116 // => colormod is never problematic for these
5117 // => BUT, we do not know s! We must assume it is problematic
5118 // then... except in GL_ONE case, where we know all invariant
5120 // src == GL_ONE_MINUS_DST_COLOR
5121 // s*(1-d) + d * dst(s, d, sa, da) == d
5122 // => s == 0 (1-d is impossible to handle for our desired result)
5123 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5124 // => colormod is never problematic for these
5125 // src == GL_SRC_ALPHA
5126 // s*sa + d * dst(s, d, sa, da) == d
5127 // => s == 0, or sa == 0
5128 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5129 // => colormod breaks in the case GL_SRC_COLOR only
5130 // src == GL_ONE_MINUS_SRC_ALPHA
5131 // s*(1-sa) + d * dst(s, d, sa, da) == d
5132 // => s == 0, or sa == 1
5133 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5134 // => colormod breaks in the case GL_SRC_COLOR only
5135 // src == GL_DST_ALPHA
5136 // s*da + d * dst(s, d, sa, da) == d
5138 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5139 // => colormod is never problematic for these
5144 case GL_ONE_MINUS_SRC_COLOR:
5146 case GL_ONE_MINUS_SRC_ALPHA:
5147 if(dst == GL_SRC_COLOR)
5152 case GL_ONE_MINUS_DST_COLOR:
5154 case GL_ONE_MINUS_DST_ALPHA:
5164 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5166 // select a permutation of the lighting shader appropriate to this
5167 // combination of texture, entity, light source, and fogging, only use the
5168 // minimum features necessary to avoid wasting rendering time in the
5169 // fragment shader on features that are not being used
5170 unsigned int permutation = 0;
5171 unsigned int mode = 0;
5172 qboolean allow_colormod;
5173 static float dummy_colormod[3] = {1, 1, 1};
5174 float *colormod = rsurface.colormod;
5176 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5177 if (rsurfacepass == RSURFPASS_BACKGROUND)
5179 // distorted background
5180 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5181 mode = SHADERMODE_WATER;
5182 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5183 mode = SHADERMODE_REFRACTION;
5186 mode = SHADERMODE_GENERIC;
5187 permutation |= SHADERPERMUTATION_DIFFUSE;
5189 GL_AlphaTest(false);
5190 GL_BlendFunc(GL_ONE, GL_ZERO);
5191 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5193 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5195 if (r_glsl_offsetmapping.integer)
5197 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5198 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5199 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5200 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5201 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5203 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5204 if (r_glsl_offsetmapping_reliefmapping.integer)
5205 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5208 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5209 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5211 permutation |= SHADERPERMUTATION_ALPHAKILL;
5212 // normalmap (deferred prepass), may use alpha test on diffuse
5213 mode = SHADERMODE_DEFERREDGEOMETRY;
5214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5215 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5216 GL_AlphaTest(false);
5217 GL_BlendFunc(GL_ONE, GL_ZERO);
5218 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5220 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5222 if (r_glsl_offsetmapping.integer)
5224 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5225 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5226 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5227 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5228 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5230 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5231 if (r_glsl_offsetmapping_reliefmapping.integer)
5232 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5236 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5238 mode = SHADERMODE_LIGHTSOURCE;
5239 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5240 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5241 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5242 permutation |= SHADERPERMUTATION_CUBEFILTER;
5243 if (diffusescale > 0)
5244 permutation |= SHADERPERMUTATION_DIFFUSE;
5245 if (specularscale > 0)
5247 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5248 if (r_shadow_glossexact.integer)
5249 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5251 if (r_refdef.fogenabled)
5252 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5253 if (rsurface.texture->colormapping)
5254 permutation |= SHADERPERMUTATION_COLORMAPPING;
5255 if (r_shadow_usingshadowmap2d)
5257 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5258 if(r_shadow_shadowmapvsdct)
5259 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5261 if (r_shadow_shadowmapsampler)
5262 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5263 if (r_shadow_shadowmappcf > 1)
5264 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5265 else if (r_shadow_shadowmappcf)
5266 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5268 if (rsurface.texture->reflectmasktexture)
5269 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5270 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5271 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5272 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5274 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5276 if (r_glsl_offsetmapping.integer)
5278 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5279 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5280 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5281 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5282 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5284 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5285 if (r_glsl_offsetmapping_reliefmapping.integer)
5286 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5289 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5290 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5291 // unshaded geometry (fullbright or ambient model lighting)
5292 mode = SHADERMODE_FLATCOLOR;
5293 ambientscale = diffusescale = specularscale = 0;
5294 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5295 permutation |= SHADERPERMUTATION_GLOW;
5296 if (r_refdef.fogenabled)
5297 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5298 if (rsurface.texture->colormapping)
5299 permutation |= SHADERPERMUTATION_COLORMAPPING;
5300 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5302 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5303 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5305 if (r_shadow_shadowmapsampler)
5306 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5307 if (r_shadow_shadowmappcf > 1)
5308 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5309 else if (r_shadow_shadowmappcf)
5310 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5312 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5313 permutation |= SHADERPERMUTATION_REFLECTION;
5314 if (rsurface.texture->reflectmasktexture)
5315 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5316 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5317 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5318 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5320 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5322 if (r_glsl_offsetmapping.integer)
5324 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5325 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5326 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5327 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5328 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5330 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5331 if (r_glsl_offsetmapping_reliefmapping.integer)
5332 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5335 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5336 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5337 // directional model lighting
5338 mode = SHADERMODE_LIGHTDIRECTION;
5339 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5340 permutation |= SHADERPERMUTATION_GLOW;
5341 permutation |= SHADERPERMUTATION_DIFFUSE;
5342 if (specularscale > 0)
5344 permutation |= SHADERPERMUTATION_SPECULAR;
5345 if (r_shadow_glossexact.integer)
5346 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5348 if (r_refdef.fogenabled)
5349 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5350 if (rsurface.texture->colormapping)
5351 permutation |= SHADERPERMUTATION_COLORMAPPING;
5352 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5354 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5355 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5357 if (r_shadow_shadowmapsampler)
5358 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5359 if (r_shadow_shadowmappcf > 1)
5360 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5361 else if (r_shadow_shadowmappcf)
5362 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5364 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5365 permutation |= SHADERPERMUTATION_REFLECTION;
5366 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5367 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5368 if (rsurface.texture->reflectmasktexture)
5369 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5370 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5371 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5372 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5374 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5376 if (r_glsl_offsetmapping.integer)
5378 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5379 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5380 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5381 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5382 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5384 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5385 if (r_glsl_offsetmapping_reliefmapping.integer)
5386 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5390 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5391 // ambient model lighting
5392 mode = SHADERMODE_LIGHTDIRECTION;
5393 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5394 permutation |= SHADERPERMUTATION_GLOW;
5395 if (r_refdef.fogenabled)
5396 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5397 if (rsurface.texture->colormapping)
5398 permutation |= SHADERPERMUTATION_COLORMAPPING;
5399 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5401 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5402 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5404 if (r_shadow_shadowmapsampler)
5405 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5406 if (r_shadow_shadowmappcf > 1)
5407 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5408 else if (r_shadow_shadowmappcf)
5409 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5411 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5412 permutation |= SHADERPERMUTATION_REFLECTION;
5413 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5414 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5415 if (rsurface.texture->reflectmasktexture)
5416 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5417 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5418 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5419 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5423 if (r_glsl_offsetmapping.integer)
5425 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5426 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5427 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5428 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5429 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5431 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5432 if (r_glsl_offsetmapping_reliefmapping.integer)
5433 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5436 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5437 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5439 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5440 permutation |= SHADERPERMUTATION_GLOW;
5441 if (r_refdef.fogenabled)
5442 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5443 if (rsurface.texture->colormapping)
5444 permutation |= SHADERPERMUTATION_COLORMAPPING;
5445 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5447 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5448 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5450 if (r_shadow_shadowmapsampler)
5451 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5452 if (r_shadow_shadowmappcf > 1)
5453 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5454 else if (r_shadow_shadowmappcf)
5455 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5458 permutation |= SHADERPERMUTATION_REFLECTION;
5459 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5460 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5461 if (rsurface.texture->reflectmasktexture)
5462 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5463 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5465 // deluxemapping (light direction texture)
5466 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5467 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5469 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5470 permutation |= SHADERPERMUTATION_DIFFUSE;
5471 if (specularscale > 0)
5473 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5474 if (r_shadow_glossexact.integer)
5475 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5478 else if (r_glsl_deluxemapping.integer >= 2)
5480 // fake deluxemapping (uniform light direction in tangentspace)
5481 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5482 permutation |= SHADERPERMUTATION_DIFFUSE;
5483 if (specularscale > 0)
5485 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5486 if (r_shadow_glossexact.integer)
5487 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5490 else if (rsurface.uselightmaptexture)
5492 // ordinary lightmapping (q1bsp, q3bsp)
5493 mode = SHADERMODE_LIGHTMAP;
5497 // ordinary vertex coloring (q3bsp)
5498 mode = SHADERMODE_VERTEXCOLOR;
5500 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5501 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5502 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5505 colormod = dummy_colormod;
5506 switch(vid.renderpath)
5508 case RENDERPATH_D3D9:
5510 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5511 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5512 R_SetupShader_SetPermutationHLSL(mode, permutation);
5513 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5514 if (mode == SHADERMODE_LIGHTSOURCE)
5516 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5517 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5521 if (mode == SHADERMODE_LIGHTDIRECTION)
5523 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5526 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5527 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5528 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5529 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5530 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5532 if (mode == SHADERMODE_LIGHTSOURCE)
5534 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5535 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5536 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5537 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5538 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5540 // additive passes are only darkened by fog, not tinted
5541 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5542 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5546 if (mode == SHADERMODE_FLATCOLOR)
5548 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5550 else if (mode == SHADERMODE_LIGHTDIRECTION)
5552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5553 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5554 hlslPSSetParameter3f(D3DPSREGISTER_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);
5555 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5556 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5557 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5558 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5563 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5564 hlslPSSetParameter3f(D3DPSREGISTER_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);
5565 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5566 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5568 // additive passes are only darkened by fog, not tinted
5569 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5570 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5572 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5573 hlslPSSetParameter4f(D3DPSREGISTER_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);
5574 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5575 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5576 hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5577 hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5578 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5579 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5580 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5582 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5583 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5584 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5585 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5586 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5587 if (rsurface.texture->pantstexture)
5588 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5590 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5591 if (rsurface.texture->shirttexture)
5592 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5594 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5595 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5596 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5597 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5598 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5599 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5600 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5601 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5603 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5604 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5605 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5606 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5607 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5608 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5609 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5610 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5611 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5612 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5613 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5614 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5615 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5616 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5617 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5618 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5619 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5620 if (rsurfacepass == RSURFPASS_BACKGROUND)
5622 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5623 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5624 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5628 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5630 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5631 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5632 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5633 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5634 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5636 R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5637 if (rsurface.rtlight)
5639 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5640 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5645 case RENDERPATH_D3D10:
5646 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5648 case RENDERPATH_D3D11:
5649 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5651 case RENDERPATH_GL20:
5652 if (gl_mesh_separatearrays.integer)
5654 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5655 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5656 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5657 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5658 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5659 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5660 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5661 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5665 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5666 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5668 R_SetupShader_SetPermutationGLSL(mode, permutation);
5669 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5670 if (mode == SHADERMODE_LIGHTSOURCE)
5672 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5673 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5674 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5675 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5676 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5677 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);
5679 // additive passes are only darkened by fog, not tinted
5680 if (r_glsl_permutation->loc_FogColor >= 0)
5681 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5682 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5686 if (mode == SHADERMODE_FLATCOLOR)
5688 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5690 else if (mode == SHADERMODE_LIGHTDIRECTION)
5692 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) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5693 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5694 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);
5695 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5696 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);
5697 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]);
5698 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]);
5702 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5703 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]);
5704 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);
5705 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5706 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);
5708 // additive passes are only darkened by fog, not tinted
5709 if (r_glsl_permutation->loc_FogColor >= 0)
5711 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5712 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5714 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5716 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);
5717 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]);
5718 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]);
5719 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5720 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5721 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5722 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5723 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5725 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5726 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5727 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5728 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]);
5729 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]);
5731 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5732 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5733 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5734 if (r_glsl_permutation->loc_Color_Pants >= 0)
5736 if (rsurface.texture->pantstexture)
5737 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5739 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5741 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5743 if (rsurface.texture->shirttexture)
5744 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5746 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5748 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]);
5749 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5750 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5751 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5752 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5753 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]);
5754 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5756 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5757 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5758 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5759 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5760 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5761 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5762 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5763 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5764 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5765 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5766 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5767 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5768 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5769 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5770 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5771 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5772 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5773 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5774 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5775 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5776 if (rsurfacepass == RSURFPASS_BACKGROUND)
5778 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5779 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5780 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5784 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5786 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5787 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5788 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5789 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5790 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5792 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5793 if (rsurface.rtlight)
5795 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5796 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5801 case RENDERPATH_CGGL:
5803 if (gl_mesh_separatearrays.integer)
5805 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5806 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5807 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5808 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5809 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5810 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5811 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5812 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5816 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5817 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5819 R_SetupShader_SetPermutationCG(mode, permutation);
5820 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5821 if (mode == SHADERMODE_LIGHTSOURCE)
5823 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5824 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5828 if (mode == SHADERMODE_LIGHTDIRECTION)
5830 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
5833 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5834 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5835 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5836 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5837 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
5840 if (mode == SHADERMODE_LIGHTSOURCE)
5842 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5843 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5844 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5845 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5846 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
5848 // additive passes are only darkened by fog, not tinted
5849 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5850 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5854 if (mode == SHADERMODE_FLATCOLOR)
5856 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5858 else if (mode == SHADERMODE_LIGHTDIRECTION)
5860 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) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
5861 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
5862 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
5863 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5864 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
5865 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
5866 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
5870 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
5871 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
5872 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
5873 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5874 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
5876 // additive passes are only darkened by fog, not tinted
5877 if (r_cg_permutation->fp_FogColor)
5879 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5880 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5882 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5885 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
5886 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
5887 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
5888 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5889 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5890 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5891 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5892 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5894 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
5895 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
5896 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5897 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5898 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5899 if (r_cg_permutation->fp_Color_Pants)
5901 if (rsurface.texture->pantstexture)
5902 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5904 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5907 if (r_cg_permutation->fp_Color_Shirt)
5909 if (rsurface.texture->shirttexture)
5910 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5912 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5915 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
5916 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5917 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5918 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5919 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5920 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
5921 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5923 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5924 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5925 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5926 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5927 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5928 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5929 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5930 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5931 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5932 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5933 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5934 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5935 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5936 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5937 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
5938 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
5939 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5940 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5941 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5942 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5943 if (rsurfacepass == RSURFPASS_BACKGROUND)
5945 if (r_cg_permutation->fp_Texture_Refraction ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
5946 else if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
5947 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
5951 if (r_cg_permutation->fp_Texture_Reflection ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
5953 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5954 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5955 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5956 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5957 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5959 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5960 if (rsurface.rtlight)
5962 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5963 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5970 case RENDERPATH_GL13:
5971 case RENDERPATH_GL11:
5976 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5978 // select a permutation of the lighting shader appropriate to this
5979 // combination of texture, entity, light source, and fogging, only use the
5980 // minimum features necessary to avoid wasting rendering time in the
5981 // fragment shader on features that are not being used
5982 unsigned int permutation = 0;
5983 unsigned int mode = 0;
5984 const float *lightcolorbase = rtlight->currentcolor;
5985 float ambientscale = rtlight->ambientscale;
5986 float diffusescale = rtlight->diffusescale;
5987 float specularscale = rtlight->specularscale;
5988 // this is the location of the light in view space
5989 vec3_t viewlightorigin;
5990 // this transforms from view space (camera) to light space (cubemap)
5991 matrix4x4_t viewtolight;
5992 matrix4x4_t lighttoview;
5993 float viewtolight16f[16];
5994 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5996 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5997 if (rtlight->currentcubemap != r_texture_whitecube)
5998 permutation |= SHADERPERMUTATION_CUBEFILTER;
5999 if (diffusescale > 0)
6000 permutation |= SHADERPERMUTATION_DIFFUSE;
6001 if (specularscale > 0)
6003 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6004 if (r_shadow_glossexact.integer)
6005 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6007 if (r_shadow_usingshadowmap2d)
6009 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6010 if (r_shadow_shadowmapvsdct)
6011 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6013 if (r_shadow_shadowmapsampler)
6014 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6015 if (r_shadow_shadowmappcf > 1)
6016 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6017 else if (r_shadow_shadowmappcf)
6018 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6020 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6021 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6022 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6023 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6024 switch(vid.renderpath)
6026 case RENDERPATH_D3D9:
6028 R_SetupShader_SetPermutationHLSL(mode, permutation);
6029 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6030 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6031 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6032 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6033 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6034 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6035 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6036 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6037 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6038 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6040 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6041 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6042 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6043 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6044 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6045 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6048 case RENDERPATH_D3D10:
6049 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6051 case RENDERPATH_D3D11:
6052 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6054 case RENDERPATH_GL20:
6055 R_SetupShader_SetPermutationGLSL(mode, permutation);
6056 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6057 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6058 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);
6059 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);
6060 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);
6061 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]);
6062 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]);
6063 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));
6064 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]);
6065 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6067 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6068 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6069 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6070 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6071 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6072 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6074 case RENDERPATH_CGGL:
6076 R_SetupShader_SetPermutationCG(mode, permutation);
6077 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6078 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6079 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
6080 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
6081 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
6082 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
6083 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
6084 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
6085 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
6086 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6088 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6089 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6090 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6091 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6092 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6093 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6096 case RENDERPATH_GL13:
6097 case RENDERPATH_GL11:
6102 #define SKINFRAME_HASH 1024
6106 int loadsequence; // incremented each level change
6107 memexpandablearray_t array;
6108 skinframe_t *hash[SKINFRAME_HASH];
6111 r_skinframe_t r_skinframe;
6113 void R_SkinFrame_PrepareForPurge(void)
6115 r_skinframe.loadsequence++;
6116 // wrap it without hitting zero
6117 if (r_skinframe.loadsequence >= 200)
6118 r_skinframe.loadsequence = 1;
6121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6125 // mark the skinframe as used for the purging code
6126 skinframe->loadsequence = r_skinframe.loadsequence;
6129 void R_SkinFrame_Purge(void)
6133 for (i = 0;i < SKINFRAME_HASH;i++)
6135 for (s = r_skinframe.hash[i];s;s = s->next)
6137 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6139 if (s->merged == s->base)
6141 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6142 R_PurgeTexture(s->stain );s->stain = NULL;
6143 R_PurgeTexture(s->merged);s->merged = NULL;
6144 R_PurgeTexture(s->base );s->base = NULL;
6145 R_PurgeTexture(s->pants );s->pants = NULL;
6146 R_PurgeTexture(s->shirt );s->shirt = NULL;
6147 R_PurgeTexture(s->nmap );s->nmap = NULL;
6148 R_PurgeTexture(s->gloss );s->gloss = NULL;
6149 R_PurgeTexture(s->glow );s->glow = NULL;
6150 R_PurgeTexture(s->fog );s->fog = NULL;
6151 R_PurgeTexture(s->reflect);s->reflect = NULL;
6152 s->loadsequence = 0;
6158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6160 char basename[MAX_QPATH];
6162 Image_StripImageExtension(name, basename, sizeof(basename));
6164 if( last == NULL ) {
6166 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6167 item = r_skinframe.hash[hashindex];
6172 // linearly search through the hash bucket
6173 for( ; item ; item = item->next ) {
6174 if( !strcmp( item->basename, basename ) ) {
6181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6185 char basename[MAX_QPATH];
6187 Image_StripImageExtension(name, basename, sizeof(basename));
6189 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6190 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6191 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6195 rtexture_t *dyntexture;
6196 // check whether its a dynamic texture
6197 dyntexture = CL_GetDynTexture( basename );
6198 if (!add && !dyntexture)
6200 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6201 memset(item, 0, sizeof(*item));
6202 strlcpy(item->basename, basename, sizeof(item->basename));
6203 item->base = dyntexture; // either NULL or dyntexture handle
6204 item->textureflags = textureflags;
6205 item->comparewidth = comparewidth;
6206 item->compareheight = compareheight;
6207 item->comparecrc = comparecrc;
6208 item->next = r_skinframe.hash[hashindex];
6209 r_skinframe.hash[hashindex] = item;
6211 else if( item->base == NULL )
6213 rtexture_t *dyntexture;
6214 // check whether its a dynamic texture
6215 // 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]
6216 dyntexture = CL_GetDynTexture( basename );
6217 item->base = dyntexture; // either NULL or dyntexture handle
6220 R_SkinFrame_MarkUsed(item);
6224 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6226 unsigned long long avgcolor[5], wsum; \
6234 for(pix = 0; pix < cnt; ++pix) \
6237 for(comp = 0; comp < 3; ++comp) \
6239 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6242 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6244 for(comp = 0; comp < 3; ++comp) \
6245 avgcolor[comp] += getpixel * w; \
6248 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6249 avgcolor[4] += getpixel; \
6251 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6253 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6254 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6255 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6256 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6259 extern cvar_t gl_picmip;
6260 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6263 unsigned char *pixels;
6264 unsigned char *bumppixels;
6265 unsigned char *basepixels = NULL;
6266 int basepixels_width = 0;
6267 int basepixels_height = 0;
6268 skinframe_t *skinframe;
6269 rtexture_t *ddsbase = NULL;
6270 qboolean ddshasalpha = false;
6271 float ddsavgcolor[4];
6272 char basename[MAX_QPATH];
6273 int miplevel = R_PicmipForFlags(textureflags);
6274 int savemiplevel = miplevel;
6277 if (cls.state == ca_dedicated)
6280 // return an existing skinframe if already loaded
6281 // if loading of the first image fails, don't make a new skinframe as it
6282 // would cause all future lookups of this to be missing
6283 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6284 if (skinframe && skinframe->base)
6287 Image_StripImageExtension(name, basename, sizeof(basename));
6289 // check for DDS texture file first
6290 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6292 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6293 if (basepixels == NULL)
6297 // FIXME handle miplevel
6299 if (developer_loading.integer)
6300 Con_Printf("loading skin \"%s\"\n", name);
6302 // we've got some pixels to store, so really allocate this new texture now
6304 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6305 skinframe->stain = NULL;
6306 skinframe->merged = NULL;
6307 skinframe->base = NULL;
6308 skinframe->pants = NULL;
6309 skinframe->shirt = NULL;
6310 skinframe->nmap = NULL;
6311 skinframe->gloss = NULL;
6312 skinframe->glow = NULL;
6313 skinframe->fog = NULL;
6314 skinframe->reflect = NULL;
6315 skinframe->hasalpha = false;
6319 skinframe->base = ddsbase;
6320 skinframe->hasalpha = ddshasalpha;
6321 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6322 if (r_loadfog && skinframe->hasalpha)
6323 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6324 //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]);
6328 basepixels_width = image_width;
6329 basepixels_height = image_height;
6330 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6331 if (textureflags & TEXF_ALPHA)
6333 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6335 if (basepixels[j] < 255)
6337 skinframe->hasalpha = true;
6341 if (r_loadfog && skinframe->hasalpha)
6343 // has transparent pixels
6344 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6345 for (j = 0;j < image_width * image_height * 4;j += 4)
6350 pixels[j+3] = basepixels[j+3];
6352 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6356 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6357 //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]);
6358 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6359 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6360 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6361 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6366 mymiplevel = savemiplevel;
6367 if (r_loadnormalmap)
6368 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6369 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6371 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6372 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6373 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6374 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6377 // _norm is the name used by tenebrae and has been adopted as standard
6378 if (r_loadnormalmap && skinframe->nmap == NULL)
6380 mymiplevel = savemiplevel;
6381 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6383 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6387 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6389 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6390 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6391 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6393 Mem_Free(bumppixels);
6395 else if (r_shadow_bumpscale_basetexture.value > 0)
6397 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6398 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6399 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6402 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6403 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6406 // _luma is supported only for tenebrae compatibility
6407 // _glow is the preferred name
6408 mymiplevel = savemiplevel;
6409 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6411 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6412 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6413 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6414 Mem_Free(pixels);pixels = NULL;
6417 mymiplevel = savemiplevel;
6418 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6420 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6421 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6422 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6427 mymiplevel = savemiplevel;
6428 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6430 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6431 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6432 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6437 mymiplevel = savemiplevel;
6438 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6440 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6441 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6442 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6447 mymiplevel = savemiplevel;
6448 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6450 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6451 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6452 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6458 Mem_Free(basepixels);
6463 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6464 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6467 unsigned char *temp1, *temp2;
6468 skinframe_t *skinframe;
6470 if (cls.state == ca_dedicated)
6473 // if already loaded just return it, otherwise make a new skinframe
6474 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6475 if (skinframe && skinframe->base)
6478 skinframe->stain = NULL;
6479 skinframe->merged = NULL;
6480 skinframe->base = NULL;
6481 skinframe->pants = NULL;
6482 skinframe->shirt = NULL;
6483 skinframe->nmap = NULL;
6484 skinframe->gloss = NULL;
6485 skinframe->glow = NULL;
6486 skinframe->fog = NULL;
6487 skinframe->reflect = NULL;
6488 skinframe->hasalpha = false;
6490 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6494 if (developer_loading.integer)
6495 Con_Printf("loading 32bit skin \"%s\"\n", name);
6497 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6499 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6500 temp2 = temp1 + width * height * 4;
6501 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6502 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6505 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6506 if (textureflags & TEXF_ALPHA)
6508 for (i = 3;i < width * height * 4;i += 4)
6510 if (skindata[i] < 255)
6512 skinframe->hasalpha = true;
6516 if (r_loadfog && skinframe->hasalpha)
6518 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6519 memcpy(fogpixels, skindata, width * height * 4);
6520 for (i = 0;i < width * height * 4;i += 4)
6521 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6522 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6523 Mem_Free(fogpixels);
6527 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6528 //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]);
6533 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6537 skinframe_t *skinframe;
6539 if (cls.state == ca_dedicated)
6542 // if already loaded just return it, otherwise make a new skinframe
6543 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6544 if (skinframe && skinframe->base)
6547 skinframe->stain = NULL;
6548 skinframe->merged = NULL;
6549 skinframe->base = NULL;
6550 skinframe->pants = NULL;
6551 skinframe->shirt = NULL;
6552 skinframe->nmap = NULL;
6553 skinframe->gloss = NULL;
6554 skinframe->glow = NULL;
6555 skinframe->fog = NULL;
6556 skinframe->reflect = NULL;
6557 skinframe->hasalpha = false;
6559 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6563 if (developer_loading.integer)
6564 Con_Printf("loading quake skin \"%s\"\n", name);
6566 // 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)
6567 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6568 memcpy(skinframe->qpixels, skindata, width*height);
6569 skinframe->qwidth = width;
6570 skinframe->qheight = height;
6573 for (i = 0;i < width * height;i++)
6574 featuresmask |= palette_featureflags[skindata[i]];
6576 skinframe->hasalpha = false;
6577 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6578 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6579 skinframe->qgeneratemerged = true;
6580 skinframe->qgeneratebase = skinframe->qhascolormapping;
6581 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6583 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6584 //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]);
6589 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6593 unsigned char *skindata;
6595 if (!skinframe->qpixels)
6598 if (!skinframe->qhascolormapping)
6599 colormapped = false;
6603 if (!skinframe->qgeneratebase)
6608 if (!skinframe->qgeneratemerged)
6612 width = skinframe->qwidth;
6613 height = skinframe->qheight;
6614 skindata = skinframe->qpixels;
6616 if (skinframe->qgeneratenmap)
6618 unsigned char *temp1, *temp2;
6619 skinframe->qgeneratenmap = false;
6620 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6621 temp2 = temp1 + width * height * 4;
6622 // use either a custom palette or the quake palette
6623 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6624 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6625 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6629 if (skinframe->qgenerateglow)
6631 skinframe->qgenerateglow = false;
6632 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6637 skinframe->qgeneratebase = false;
6638 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6639 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6640 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6644 skinframe->qgeneratemerged = false;
6645 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6648 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6650 Mem_Free(skinframe->qpixels);
6651 skinframe->qpixels = NULL;
6655 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)
6658 skinframe_t *skinframe;
6660 if (cls.state == ca_dedicated)
6663 // if already loaded just return it, otherwise make a new skinframe
6664 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6665 if (skinframe && skinframe->base)
6668 skinframe->stain = NULL;
6669 skinframe->merged = NULL;
6670 skinframe->base = NULL;
6671 skinframe->pants = NULL;
6672 skinframe->shirt = NULL;
6673 skinframe->nmap = NULL;
6674 skinframe->gloss = NULL;
6675 skinframe->glow = NULL;
6676 skinframe->fog = NULL;
6677 skinframe->reflect = NULL;
6678 skinframe->hasalpha = false;
6680 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6684 if (developer_loading.integer)
6685 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6687 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6688 if (textureflags & TEXF_ALPHA)
6690 for (i = 0;i < width * height;i++)
6692 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6694 skinframe->hasalpha = true;
6698 if (r_loadfog && skinframe->hasalpha)
6699 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6702 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6703 //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]);
6708 skinframe_t *R_SkinFrame_LoadMissing(void)
6710 skinframe_t *skinframe;
6712 if (cls.state == ca_dedicated)
6715 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6716 skinframe->stain = NULL;
6717 skinframe->merged = NULL;
6718 skinframe->base = NULL;
6719 skinframe->pants = NULL;
6720 skinframe->shirt = NULL;
6721 skinframe->nmap = NULL;
6722 skinframe->gloss = NULL;
6723 skinframe->glow = NULL;
6724 skinframe->fog = NULL;
6725 skinframe->reflect = NULL;
6726 skinframe->hasalpha = false;
6728 skinframe->avgcolor[0] = rand() / RAND_MAX;
6729 skinframe->avgcolor[1] = rand() / RAND_MAX;
6730 skinframe->avgcolor[2] = rand() / RAND_MAX;
6731 skinframe->avgcolor[3] = 1;
6736 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6737 typedef struct suffixinfo_s
6740 qboolean flipx, flipy, flipdiagonal;
6743 static suffixinfo_t suffix[3][6] =
6746 {"px", false, false, false},
6747 {"nx", false, false, false},
6748 {"py", false, false, false},
6749 {"ny", false, false, false},
6750 {"pz", false, false, false},
6751 {"nz", false, false, false}
6754 {"posx", false, false, false},
6755 {"negx", false, false, false},
6756 {"posy", false, false, false},
6757 {"negy", false, false, false},
6758 {"posz", false, false, false},
6759 {"negz", false, false, false}
6762 {"rt", true, false, true},
6763 {"lf", false, true, true},
6764 {"ft", true, true, false},
6765 {"bk", false, false, false},
6766 {"up", true, false, true},
6767 {"dn", true, false, true}
6771 static int componentorder[4] = {0, 1, 2, 3};
6773 rtexture_t *R_LoadCubemap(const char *basename)
6775 int i, j, cubemapsize;
6776 unsigned char *cubemappixels, *image_buffer;
6777 rtexture_t *cubemaptexture;
6779 // must start 0 so the first loadimagepixels has no requested width/height
6781 cubemappixels = NULL;
6782 cubemaptexture = NULL;
6783 // keep trying different suffix groups (posx, px, rt) until one loads
6784 for (j = 0;j < 3 && !cubemappixels;j++)
6786 // load the 6 images in the suffix group
6787 for (i = 0;i < 6;i++)
6789 // generate an image name based on the base and and suffix
6790 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6792 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6794 // an image loaded, make sure width and height are equal
6795 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6797 // if this is the first image to load successfully, allocate the cubemap memory
6798 if (!cubemappixels && image_width >= 1)
6800 cubemapsize = image_width;
6801 // note this clears to black, so unavailable sides are black
6802 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6804 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6806 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);
6809 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6811 Mem_Free(image_buffer);
6815 // if a cubemap loaded, upload it
6818 if (developer_loading.integer)
6819 Con_Printf("loading cubemap \"%s\"\n", basename);
6821 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6822 Mem_Free(cubemappixels);
6826 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6827 if (developer_loading.integer)
6829 Con_Printf("(tried tried images ");
6830 for (j = 0;j < 3;j++)
6831 for (i = 0;i < 6;i++)
6832 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6833 Con_Print(" and was unable to find any of them).\n");
6836 return cubemaptexture;
6839 rtexture_t *R_GetCubemap(const char *basename)
6842 for (i = 0;i < r_texture_numcubemaps;i++)
6843 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6844 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6845 if (i >= MAX_CUBEMAPS)
6846 return r_texture_whitecube;
6847 r_texture_numcubemaps++;
6848 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6849 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6850 return r_texture_cubemaps[i].texture;
6853 void R_FreeCubemaps(void)
6856 for (i = 0;i < r_texture_numcubemaps;i++)
6858 if (developer_loading.integer)
6859 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6860 if (r_texture_cubemaps[i].texture)
6861 R_FreeTexture(r_texture_cubemaps[i].texture);
6863 r_texture_numcubemaps = 0;
6866 void R_Main_FreeViewCache(void)
6868 if (r_refdef.viewcache.entityvisible)
6869 Mem_Free(r_refdef.viewcache.entityvisible);
6870 if (r_refdef.viewcache.world_pvsbits)
6871 Mem_Free(r_refdef.viewcache.world_pvsbits);
6872 if (r_refdef.viewcache.world_leafvisible)
6873 Mem_Free(r_refdef.viewcache.world_leafvisible);
6874 if (r_refdef.viewcache.world_surfacevisible)
6875 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6876 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6879 void R_Main_ResizeViewCache(void)
6881 int numentities = r_refdef.scene.numentities;
6882 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6883 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6884 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6885 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6886 if (r_refdef.viewcache.maxentities < numentities)
6888 r_refdef.viewcache.maxentities = numentities;
6889 if (r_refdef.viewcache.entityvisible)
6890 Mem_Free(r_refdef.viewcache.entityvisible);
6891 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6893 if (r_refdef.viewcache.world_numclusters != numclusters)
6895 r_refdef.viewcache.world_numclusters = numclusters;
6896 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6897 if (r_refdef.viewcache.world_pvsbits)
6898 Mem_Free(r_refdef.viewcache.world_pvsbits);
6899 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6901 if (r_refdef.viewcache.world_numleafs != numleafs)
6903 r_refdef.viewcache.world_numleafs = numleafs;
6904 if (r_refdef.viewcache.world_leafvisible)
6905 Mem_Free(r_refdef.viewcache.world_leafvisible);
6906 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6908 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6910 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6911 if (r_refdef.viewcache.world_surfacevisible)
6912 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6913 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6917 extern rtexture_t *loadingscreentexture;
6918 void gl_main_start(void)
6920 loadingscreentexture = NULL;
6921 r_texture_blanknormalmap = NULL;
6922 r_texture_white = NULL;
6923 r_texture_grey128 = NULL;
6924 r_texture_black = NULL;
6925 r_texture_whitecube = NULL;
6926 r_texture_normalizationcube = NULL;
6927 r_texture_fogattenuation = NULL;
6928 r_texture_fogheighttexture = NULL;
6929 r_texture_gammaramps = NULL;
6930 r_texture_numcubemaps = 0;
6932 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6933 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6935 switch(vid.renderpath)
6937 case RENDERPATH_GL20:
6938 case RENDERPATH_CGGL:
6939 case RENDERPATH_D3D9:
6940 case RENDERPATH_D3D10:
6941 case RENDERPATH_D3D11:
6942 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6943 Cvar_SetValueQuick(&gl_combine, 1);
6944 Cvar_SetValueQuick(&r_glsl, 1);
6945 r_loadnormalmap = true;
6949 case RENDERPATH_GL13:
6950 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6951 Cvar_SetValueQuick(&gl_combine, 1);
6952 Cvar_SetValueQuick(&r_glsl, 0);
6953 r_loadnormalmap = false;
6954 r_loadgloss = false;
6957 case RENDERPATH_GL11:
6958 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6959 Cvar_SetValueQuick(&gl_combine, 0);
6960 Cvar_SetValueQuick(&r_glsl, 0);
6961 r_loadnormalmap = false;
6962 r_loadgloss = false;
6968 R_FrameData_Reset();
6972 memset(r_queries, 0, sizeof(r_queries));
6974 r_qwskincache = NULL;
6975 r_qwskincache_size = 0;
6977 // set up r_skinframe loading system for textures
6978 memset(&r_skinframe, 0, sizeof(r_skinframe));
6979 r_skinframe.loadsequence = 1;
6980 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6982 r_main_texturepool = R_AllocTexturePool();
6983 R_BuildBlankTextures();
6985 if (vid.support.arb_texture_cube_map)
6988 R_BuildNormalizationCube();
6990 r_texture_fogattenuation = NULL;
6991 r_texture_fogheighttexture = NULL;
6992 r_texture_gammaramps = NULL;
6993 //r_texture_fogintensity = NULL;
6994 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6995 memset(&r_waterstate, 0, sizeof(r_waterstate));
6996 r_glsl_permutation = NULL;
6997 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6998 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6999 glslshaderstring = NULL;
7001 r_cg_permutation = NULL;
7002 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7003 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7004 cgshaderstring = NULL;
7007 r_hlsl_permutation = NULL;
7008 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7009 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7010 hlslshaderstring = NULL;
7012 memset(&r_svbsp, 0, sizeof (r_svbsp));
7014 r_refdef.fogmasktable_density = 0;
7017 void gl_main_shutdown(void)
7020 R_FrameData_Reset();
7022 R_Main_FreeViewCache();
7024 switch(vid.renderpath)
7026 case RENDERPATH_GL11:
7027 case RENDERPATH_GL13:
7028 case RENDERPATH_GL20:
7029 case RENDERPATH_CGGL:
7031 qglDeleteQueriesARB(r_maxqueries, r_queries);
7033 case RENDERPATH_D3D9:
7034 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7036 case RENDERPATH_D3D10:
7037 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7039 case RENDERPATH_D3D11:
7040 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7046 memset(r_queries, 0, sizeof(r_queries));
7048 r_qwskincache = NULL;
7049 r_qwskincache_size = 0;
7051 // clear out the r_skinframe state
7052 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7053 memset(&r_skinframe, 0, sizeof(r_skinframe));
7056 Mem_Free(r_svbsp.nodes);
7057 memset(&r_svbsp, 0, sizeof (r_svbsp));
7058 R_FreeTexturePool(&r_main_texturepool);
7059 loadingscreentexture = NULL;
7060 r_texture_blanknormalmap = NULL;
7061 r_texture_white = NULL;
7062 r_texture_grey128 = NULL;
7063 r_texture_black = NULL;
7064 r_texture_whitecube = NULL;
7065 r_texture_normalizationcube = NULL;
7066 r_texture_fogattenuation = NULL;
7067 r_texture_fogheighttexture = NULL;
7068 r_texture_gammaramps = NULL;
7069 r_texture_numcubemaps = 0;
7070 //r_texture_fogintensity = NULL;
7071 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7072 memset(&r_waterstate, 0, sizeof(r_waterstate));
7076 extern void CL_ParseEntityLump(char *entitystring);
7077 void gl_main_newmap(void)
7079 // FIXME: move this code to client
7080 char *entities, entname[MAX_QPATH];
7082 Mem_Free(r_qwskincache);
7083 r_qwskincache = NULL;
7084 r_qwskincache_size = 0;
7087 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7088 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7090 CL_ParseEntityLump(entities);
7094 if (cl.worldmodel->brush.entities)
7095 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7097 R_Main_FreeViewCache();
7099 R_FrameData_Reset();
7102 void GL_Main_Init(void)
7104 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7106 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7107 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7108 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7109 if (gamemode == GAME_NEHAHRA)
7111 Cvar_RegisterVariable (&gl_fogenable);
7112 Cvar_RegisterVariable (&gl_fogdensity);
7113 Cvar_RegisterVariable (&gl_fogred);
7114 Cvar_RegisterVariable (&gl_foggreen);
7115 Cvar_RegisterVariable (&gl_fogblue);
7116 Cvar_RegisterVariable (&gl_fogstart);
7117 Cvar_RegisterVariable (&gl_fogend);
7118 Cvar_RegisterVariable (&gl_skyclip);
7120 Cvar_RegisterVariable(&r_motionblur);
7121 Cvar_RegisterVariable(&r_motionblur_maxblur);
7122 Cvar_RegisterVariable(&r_motionblur_bmin);
7123 Cvar_RegisterVariable(&r_motionblur_vmin);
7124 Cvar_RegisterVariable(&r_motionblur_vmax);
7125 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7126 Cvar_RegisterVariable(&r_motionblur_randomize);
7127 Cvar_RegisterVariable(&r_damageblur);
7128 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7129 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7130 Cvar_RegisterVariable(&r_equalize_entities_by);
7131 Cvar_RegisterVariable(&r_equalize_entities_to);
7132 Cvar_RegisterVariable(&r_depthfirst);
7133 Cvar_RegisterVariable(&r_useinfinitefarclip);
7134 Cvar_RegisterVariable(&r_farclip_base);
7135 Cvar_RegisterVariable(&r_farclip_world);
7136 Cvar_RegisterVariable(&r_nearclip);
7137 Cvar_RegisterVariable(&r_showbboxes);
7138 Cvar_RegisterVariable(&r_showsurfaces);
7139 Cvar_RegisterVariable(&r_showtris);
7140 Cvar_RegisterVariable(&r_shownormals);
7141 Cvar_RegisterVariable(&r_showlighting);
7142 Cvar_RegisterVariable(&r_showshadowvolumes);
7143 Cvar_RegisterVariable(&r_showcollisionbrushes);
7144 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7145 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7146 Cvar_RegisterVariable(&r_showdisabledepthtest);
7147 Cvar_RegisterVariable(&r_drawportals);
7148 Cvar_RegisterVariable(&r_drawentities);
7149 Cvar_RegisterVariable(&r_draw2d);
7150 Cvar_RegisterVariable(&r_drawworld);
7151 Cvar_RegisterVariable(&r_cullentities_trace);
7152 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7153 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7154 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7155 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7156 Cvar_RegisterVariable(&r_drawviewmodel);
7157 Cvar_RegisterVariable(&r_drawexteriormodel);
7158 Cvar_RegisterVariable(&r_speeds);
7159 Cvar_RegisterVariable(&r_fullbrights);
7160 Cvar_RegisterVariable(&r_wateralpha);
7161 Cvar_RegisterVariable(&r_dynamic);
7162 Cvar_RegisterVariable(&r_fullbright);
7163 Cvar_RegisterVariable(&r_shadows);
7164 Cvar_RegisterVariable(&r_shadows_darken);
7165 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7166 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7167 Cvar_RegisterVariable(&r_shadows_throwdistance);
7168 Cvar_RegisterVariable(&r_shadows_throwdirection);
7169 Cvar_RegisterVariable(&r_shadows_focus);
7170 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7171 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7172 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7173 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7174 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7175 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7176 Cvar_RegisterVariable(&r_fog_exp2);
7177 Cvar_RegisterVariable(&r_drawfog);
7178 Cvar_RegisterVariable(&r_transparentdepthmasking);
7179 Cvar_RegisterVariable(&r_texture_dds_load);
7180 Cvar_RegisterVariable(&r_texture_dds_save);
7181 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7182 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7183 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7184 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7185 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7186 Cvar_RegisterVariable(&r_textureunits);
7187 Cvar_RegisterVariable(&gl_combine);
7188 Cvar_RegisterVariable(&r_glsl);
7189 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7190 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7191 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7192 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7193 Cvar_RegisterVariable(&r_glsl_postprocess);
7194 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7195 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7196 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7197 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7198 Cvar_RegisterVariable(&r_water);
7199 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7200 Cvar_RegisterVariable(&r_water_clippingplanebias);
7201 Cvar_RegisterVariable(&r_water_refractdistort);
7202 Cvar_RegisterVariable(&r_water_reflectdistort);
7203 Cvar_RegisterVariable(&r_lerpsprites);
7204 Cvar_RegisterVariable(&r_lerpmodels);
7205 Cvar_RegisterVariable(&r_lerplightstyles);
7206 Cvar_RegisterVariable(&r_waterscroll);
7207 Cvar_RegisterVariable(&r_bloom);
7208 Cvar_RegisterVariable(&r_bloom_colorscale);
7209 Cvar_RegisterVariable(&r_bloom_brighten);
7210 Cvar_RegisterVariable(&r_bloom_blur);
7211 Cvar_RegisterVariable(&r_bloom_resolution);
7212 Cvar_RegisterVariable(&r_bloom_colorexponent);
7213 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7214 Cvar_RegisterVariable(&r_hdr);
7215 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7216 Cvar_RegisterVariable(&r_hdr_glowintensity);
7217 Cvar_RegisterVariable(&r_hdr_range);
7218 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7219 Cvar_RegisterVariable(&developer_texturelogging);
7220 Cvar_RegisterVariable(&gl_lightmaps);
7221 Cvar_RegisterVariable(&r_test);
7222 Cvar_RegisterVariable(&r_glsl_saturation);
7223 Cvar_RegisterVariable(&r_framedatasize);
7224 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7225 Cvar_SetValue("r_fullbrights", 0);
7226 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7228 Cvar_RegisterVariable(&r_track_sprites);
7229 Cvar_RegisterVariable(&r_track_sprites_flags);
7230 Cvar_RegisterVariable(&r_track_sprites_scalew);
7231 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7232 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7233 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7236 extern void R_Textures_Init(void);
7237 extern void GL_Draw_Init(void);
7238 extern void GL_Main_Init(void);
7239 extern void R_Shadow_Init(void);
7240 extern void R_Sky_Init(void);
7241 extern void GL_Surf_Init(void);
7242 extern void R_Particles_Init(void);
7243 extern void R_Explosion_Init(void);
7244 extern void gl_backend_init(void);
7245 extern void Sbar_Init(void);
7246 extern void R_LightningBeams_Init(void);
7247 extern void Mod_RenderInit(void);
7248 extern void Font_Init(void);
7250 void Render_Init(void)
7263 R_LightningBeams_Init();
7272 extern char *ENGINE_EXTENSIONS;
7275 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7276 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7277 gl_version = (const char *)qglGetString(GL_VERSION);
7278 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7282 if (!gl_platformextensions)
7283 gl_platformextensions = "";
7285 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7286 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7287 Con_Printf("GL_VERSION: %s\n", gl_version);
7288 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7289 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7291 VID_CheckExtensions();
7293 // LordHavoc: report supported extensions
7294 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7296 // clear to black (loading plaque will be seen over this)
7297 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7300 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7304 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7306 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7309 p = r_refdef.view.frustum + i;
7314 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7318 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7322 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7326 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7330 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7334 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7338 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7342 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7350 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7354 for (i = 0;i < numplanes;i++)
7361 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7365 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7369 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7373 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7377 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7381 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7385 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7389 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7397 //==================================================================================
7399 // LordHavoc: this stores temporary data used within the same frame
7401 qboolean r_framedata_failed;
7402 static size_t r_framedata_size;
7403 static size_t r_framedata_current;
7404 static void *r_framedata_base;
7406 void R_FrameData_Reset(void)
7408 if (r_framedata_base)
7409 Mem_Free(r_framedata_base);
7410 r_framedata_base = NULL;
7411 r_framedata_size = 0;
7412 r_framedata_current = 0;
7413 r_framedata_failed = false;
7416 void R_FrameData_NewFrame(void)
7419 if (r_framedata_failed)
7420 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7421 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7422 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7423 if (r_framedata_size != wantedsize)
7425 r_framedata_size = wantedsize;
7426 if (r_framedata_base)
7427 Mem_Free(r_framedata_base);
7428 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7430 r_framedata_current = 0;
7431 r_framedata_failed = false;
7434 void *R_FrameData_Alloc(size_t size)
7438 // align to 16 byte boundary
7439 size = (size + 15) & ~15;
7440 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7441 r_framedata_current += size;
7444 if (r_framedata_current > r_framedata_size)
7445 r_framedata_failed = true;
7447 // return NULL on everything after a failure
7448 if (r_framedata_failed)
7454 void *R_FrameData_Store(size_t size, void *data)
7456 void *d = R_FrameData_Alloc(size);
7458 memcpy(d, data, size);
7462 //==================================================================================
7464 // LordHavoc: animcache originally written by Echon, rewritten since then
7467 * Animation cache prevents re-generating mesh data for an animated model
7468 * multiple times in one frame for lighting, shadowing, reflections, etc.
7471 void R_AnimCache_Free(void)
7475 void R_AnimCache_ClearCache(void)
7478 entity_render_t *ent;
7480 for (i = 0;i < r_refdef.scene.numentities;i++)
7482 ent = r_refdef.scene.entities[i];
7483 ent->animcache_vertex3f = NULL;
7484 ent->animcache_normal3f = NULL;
7485 ent->animcache_svector3f = NULL;
7486 ent->animcache_tvector3f = NULL;
7487 ent->animcache_vertexposition = NULL;
7488 ent->animcache_vertexmesh = NULL;
7489 ent->animcache_vertexpositionbuffer = NULL;
7490 ent->animcache_vertexmeshbuffer = NULL;
7494 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7498 // identical memory layout, so no need to allocate...
7499 // this also provides the vertexposition structure to everything, e.g.
7500 // depth masked rendering currently uses it even if having separate
7502 // NOTE: get rid of this optimization if changing it to e.g. 4f
7503 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7506 // get rid of following uses of VERTEXPOSITION, change to the array:
7507 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7508 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7509 // R_DrawTextureSurfaceList_DepthOnly
7510 // R_Q1BSP_DrawShadowMap
7512 switch(vid.renderpath)
7514 case RENDERPATH_GL20:
7515 case RENDERPATH_CGGL:
7516 // need the meshbuffers if !gl_mesh_separatearrays.integer
7517 if (gl_mesh_separatearrays.integer)
7520 case RENDERPATH_D3D9:
7521 case RENDERPATH_D3D10:
7522 case RENDERPATH_D3D11:
7523 // always need the meshbuffers
7525 case RENDERPATH_GL13:
7526 case RENDERPATH_GL11:
7527 // never need the meshbuffers
7531 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7532 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7534 if (!ent->animcache_vertexposition)
7535 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7537 if (ent->animcache_vertexposition)
7540 for (i = 0;i < numvertices;i++)
7541 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7543 // TODO: upload vertex buffer?
7545 if (ent->animcache_vertexmesh)
7547 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7548 for (i = 0;i < numvertices;i++)
7549 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7550 if (ent->animcache_svector3f)
7551 for (i = 0;i < numvertices;i++)
7552 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7553 if (ent->animcache_tvector3f)
7554 for (i = 0;i < numvertices;i++)
7555 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7556 if (ent->animcache_normal3f)
7557 for (i = 0;i < numvertices;i++)
7558 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7559 // TODO: upload vertex buffer?
7563 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7565 dp_model_t *model = ent->model;
7567 // see if it's already cached this frame
7568 if (ent->animcache_vertex3f)
7570 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7571 if (wantnormals || wanttangents)
7573 if (ent->animcache_normal3f)
7574 wantnormals = false;
7575 if (ent->animcache_svector3f)
7576 wanttangents = false;
7577 if (wantnormals || wanttangents)
7579 numvertices = model->surfmesh.num_vertices;
7581 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7584 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7585 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7587 if (!r_framedata_failed)
7589 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7590 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7597 // see if this ent is worth caching
7598 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7600 // get some memory for this entity and generate mesh data
7601 numvertices = model->surfmesh.num_vertices;
7602 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7604 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7607 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7608 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7610 if (!r_framedata_failed)
7612 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7613 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7616 return !r_framedata_failed;
7619 void R_AnimCache_CacheVisibleEntities(void)
7622 qboolean wantnormals = true;
7623 qboolean wanttangents = !r_showsurfaces.integer;
7625 switch(vid.renderpath)
7627 case RENDERPATH_GL20:
7628 case RENDERPATH_CGGL:
7629 case RENDERPATH_D3D9:
7630 case RENDERPATH_D3D10:
7631 case RENDERPATH_D3D11:
7633 case RENDERPATH_GL13:
7634 case RENDERPATH_GL11:
7635 wanttangents = false;
7639 if (r_shownormals.integer)
7640 wanttangents = wantnormals = true;
7642 // TODO: thread this
7643 // NOTE: R_PrepareRTLights() also caches entities
7645 for (i = 0;i < r_refdef.scene.numentities;i++)
7646 if (r_refdef.viewcache.entityvisible[i])
7647 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7650 //==================================================================================
7652 static void R_View_UpdateEntityLighting (void)
7655 entity_render_t *ent;
7656 vec3_t tempdiffusenormal, avg;
7657 vec_t f, fa, fd, fdd;
7658 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7660 for (i = 0;i < r_refdef.scene.numentities;i++)
7662 ent = r_refdef.scene.entities[i];
7664 // skip unseen models
7665 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7669 if (ent->model && ent->model->brush.num_leafs)
7671 // TODO: use modellight for r_ambient settings on world?
7672 VectorSet(ent->modellight_ambient, 0, 0, 0);
7673 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7674 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7678 // fetch the lighting from the worldmodel data
7679 VectorClear(ent->modellight_ambient);
7680 VectorClear(ent->modellight_diffuse);
7681 VectorClear(tempdiffusenormal);
7682 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7685 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7686 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7687 if(ent->flags & RENDER_EQUALIZE)
7689 // first fix up ambient lighting...
7690 if(r_equalize_entities_minambient.value > 0)
7692 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7695 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7696 if(fa < r_equalize_entities_minambient.value * fd)
7699 // fa'/fd' = minambient
7700 // fa'+0.25*fd' = fa+0.25*fd
7702 // fa' = fd' * minambient
7703 // fd'*(0.25+minambient) = fa+0.25*fd
7705 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7706 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7708 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7709 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
7710 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7711 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7716 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7718 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7719 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7722 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7723 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7724 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7730 VectorSet(ent->modellight_ambient, 1, 1, 1);
7732 // move the light direction into modelspace coordinates for lighting code
7733 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7734 if(VectorLength2(ent->modellight_lightdir) == 0)
7735 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7736 VectorNormalize(ent->modellight_lightdir);
7740 #define MAX_LINEOFSIGHTTRACES 64
7742 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7745 vec3_t boxmins, boxmaxs;
7748 dp_model_t *model = r_refdef.scene.worldmodel;
7750 if (!model || !model->brush.TraceLineOfSight)
7753 // expand the box a little
7754 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7755 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7756 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7757 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7758 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7759 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7761 // return true if eye is inside enlarged box
7762 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7766 VectorCopy(eye, start);
7767 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7768 if (model->brush.TraceLineOfSight(model, start, end))
7771 // try various random positions
7772 for (i = 0;i < numsamples;i++)
7774 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7775 if (model->brush.TraceLineOfSight(model, start, end))
7783 static void R_View_UpdateEntityVisible (void)
7788 entity_render_t *ent;
7790 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7791 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7792 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7793 : RENDER_EXTERIORMODEL;
7794 if (!r_drawviewmodel.integer)
7795 renderimask |= RENDER_VIEWMODEL;
7796 if (!r_drawexteriormodel.integer)
7797 renderimask |= RENDER_EXTERIORMODEL;
7798 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7800 // worldmodel can check visibility
7801 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7802 for (i = 0;i < r_refdef.scene.numentities;i++)
7804 ent = r_refdef.scene.entities[i];
7805 if (!(ent->flags & renderimask))
7806 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7807 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))
7808 r_refdef.viewcache.entityvisible[i] = true;
7810 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7811 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7813 for (i = 0;i < r_refdef.scene.numentities;i++)
7815 ent = r_refdef.scene.entities[i];
7816 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7818 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7820 continue; // temp entities do pvs only
7821 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7822 ent->last_trace_visibility = realtime;
7823 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7824 r_refdef.viewcache.entityvisible[i] = 0;
7831 // no worldmodel or it can't check visibility
7832 for (i = 0;i < r_refdef.scene.numentities;i++)
7834 ent = r_refdef.scene.entities[i];
7835 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));
7840 /// only used if skyrendermasked, and normally returns false
7841 int R_DrawBrushModelsSky (void)
7844 entity_render_t *ent;
7847 for (i = 0;i < r_refdef.scene.numentities;i++)
7849 if (!r_refdef.viewcache.entityvisible[i])
7851 ent = r_refdef.scene.entities[i];
7852 if (!ent->model || !ent->model->DrawSky)
7854 ent->model->DrawSky(ent);
7860 static void R_DrawNoModel(entity_render_t *ent);
7861 static void R_DrawModels(void)
7864 entity_render_t *ent;
7866 for (i = 0;i < r_refdef.scene.numentities;i++)
7868 if (!r_refdef.viewcache.entityvisible[i])
7870 ent = r_refdef.scene.entities[i];
7871 r_refdef.stats.entities++;
7872 if (ent->model && ent->model->Draw != NULL)
7873 ent->model->Draw(ent);
7879 static void R_DrawModelsDepth(void)
7882 entity_render_t *ent;
7884 for (i = 0;i < r_refdef.scene.numentities;i++)
7886 if (!r_refdef.viewcache.entityvisible[i])
7888 ent = r_refdef.scene.entities[i];
7889 if (ent->model && ent->model->DrawDepth != NULL)
7890 ent->model->DrawDepth(ent);
7894 static void R_DrawModelsDebug(void)
7897 entity_render_t *ent;
7899 for (i = 0;i < r_refdef.scene.numentities;i++)
7901 if (!r_refdef.viewcache.entityvisible[i])
7903 ent = r_refdef.scene.entities[i];
7904 if (ent->model && ent->model->DrawDebug != NULL)
7905 ent->model->DrawDebug(ent);
7909 static void R_DrawModelsAddWaterPlanes(void)
7912 entity_render_t *ent;
7914 for (i = 0;i < r_refdef.scene.numentities;i++)
7916 if (!r_refdef.viewcache.entityvisible[i])
7918 ent = r_refdef.scene.entities[i];
7919 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7920 ent->model->DrawAddWaterPlanes(ent);
7924 static void R_View_SetFrustum(void)
7927 double slopex, slopey;
7928 vec3_t forward, left, up, origin;
7930 // we can't trust r_refdef.view.forward and friends in reflected scenes
7931 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7934 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7935 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7936 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7937 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7938 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7939 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7940 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7941 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7942 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7943 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7944 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7945 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7949 zNear = r_refdef.nearclip;
7950 nudge = 1.0 - 1.0 / (1<<23);
7951 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7952 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7953 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7954 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7955 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7956 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7957 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7958 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7964 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7965 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7966 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7967 r_refdef.view.frustum[0].dist = m[15] - m[12];
7969 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7970 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7971 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7972 r_refdef.view.frustum[1].dist = m[15] + m[12];
7974 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7975 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7976 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7977 r_refdef.view.frustum[2].dist = m[15] - m[13];
7979 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7980 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7981 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7982 r_refdef.view.frustum[3].dist = m[15] + m[13];
7984 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7985 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7986 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7987 r_refdef.view.frustum[4].dist = m[15] - m[14];
7989 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7990 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7991 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7992 r_refdef.view.frustum[5].dist = m[15] + m[14];
7995 if (r_refdef.view.useperspective)
7997 slopex = 1.0 / r_refdef.view.frustum_x;
7998 slopey = 1.0 / r_refdef.view.frustum_y;
7999 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8000 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
8001 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
8002 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
8003 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8005 // Leaving those out was a mistake, those were in the old code, and they
8006 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8007 // I couldn't reproduce it after adding those normalizations. --blub
8008 VectorNormalize(r_refdef.view.frustum[0].normal);
8009 VectorNormalize(r_refdef.view.frustum[1].normal);
8010 VectorNormalize(r_refdef.view.frustum[2].normal);
8011 VectorNormalize(r_refdef.view.frustum[3].normal);
8013 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8014 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]);
8015 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]);
8016 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]);
8017 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]);
8019 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8020 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8021 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8022 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8023 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8027 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8028 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8029 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8030 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8031 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8032 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8033 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8034 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8035 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8036 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8038 r_refdef.view.numfrustumplanes = 5;
8040 if (r_refdef.view.useclipplane)
8042 r_refdef.view.numfrustumplanes = 6;
8043 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8046 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8047 PlaneClassify(r_refdef.view.frustum + i);
8049 // LordHavoc: note to all quake engine coders, Quake had a special case
8050 // for 90 degrees which assumed a square view (wrong), so I removed it,
8051 // Quake2 has it disabled as well.
8053 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8054 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8055 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8056 //PlaneClassify(&frustum[0]);
8058 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8059 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8060 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8061 //PlaneClassify(&frustum[1]);
8063 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8064 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8065 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8066 //PlaneClassify(&frustum[2]);
8068 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8069 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8070 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8071 //PlaneClassify(&frustum[3]);
8074 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8075 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8076 //PlaneClassify(&frustum[4]);
8079 void R_View_Update(void)
8081 R_Main_ResizeViewCache();
8082 R_View_SetFrustum();
8083 R_View_WorldVisibility(r_refdef.view.useclipplane);
8084 R_View_UpdateEntityVisible();
8085 R_View_UpdateEntityLighting();
8088 void R_SetupView(qboolean allowwaterclippingplane)
8090 const float *customclipplane = NULL;
8092 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8094 // LordHavoc: couldn't figure out how to make this approach the
8095 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8096 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8097 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8098 dist = r_refdef.view.clipplane.dist;
8099 plane[0] = r_refdef.view.clipplane.normal[0];
8100 plane[1] = r_refdef.view.clipplane.normal[1];
8101 plane[2] = r_refdef.view.clipplane.normal[2];
8103 customclipplane = plane;
8106 if (!r_refdef.view.useperspective)
8107 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);
8108 else if (vid.stencil && r_useinfinitefarclip.integer)
8109 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);
8111 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);
8112 R_SetViewport(&r_refdef.view.viewport);
8115 void R_EntityMatrix(const matrix4x4_t *matrix)
8117 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8119 gl_modelmatrixchanged = false;
8120 gl_modelmatrix = *matrix;
8121 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8122 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8123 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8124 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8126 switch(vid.renderpath)
8128 case RENDERPATH_D3D9:
8130 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8131 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8134 case RENDERPATH_D3D10:
8135 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8137 case RENDERPATH_D3D11:
8138 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8140 case RENDERPATH_GL20:
8141 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8142 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8143 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8145 case RENDERPATH_CGGL:
8148 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8149 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8150 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8153 case RENDERPATH_GL13:
8154 case RENDERPATH_GL11:
8155 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8161 void R_ResetViewRendering2D(void)
8163 r_viewport_t viewport;
8166 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8167 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);
8168 R_SetViewport(&viewport);
8169 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8170 GL_Color(1, 1, 1, 1);
8171 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8172 GL_BlendFunc(GL_ONE, GL_ZERO);
8173 GL_AlphaTest(false);
8174 GL_ScissorTest(false);
8175 GL_DepthMask(false);
8176 GL_DepthRange(0, 1);
8177 GL_DepthTest(false);
8178 GL_DepthFunc(GL_LEQUAL);
8179 R_EntityMatrix(&identitymatrix);
8180 R_Mesh_ResetTextureState();
8181 GL_PolygonOffset(0, 0);
8182 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8183 switch(vid.renderpath)
8185 case RENDERPATH_GL11:
8186 case RENDERPATH_GL13:
8187 case RENDERPATH_GL20:
8188 case RENDERPATH_CGGL:
8189 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8191 case RENDERPATH_D3D9:
8192 case RENDERPATH_D3D10:
8193 case RENDERPATH_D3D11:
8196 GL_CullFace(GL_NONE);
8199 void R_ResetViewRendering3D(void)
8204 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8205 GL_Color(1, 1, 1, 1);
8206 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8207 GL_BlendFunc(GL_ONE, GL_ZERO);
8208 GL_AlphaTest(false);
8209 GL_ScissorTest(true);
8211 GL_DepthRange(0, 1);
8213 GL_DepthFunc(GL_LEQUAL);
8214 R_EntityMatrix(&identitymatrix);
8215 R_Mesh_ResetTextureState();
8216 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8217 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8218 switch(vid.renderpath)
8220 case RENDERPATH_GL11:
8221 case RENDERPATH_GL13:
8222 case RENDERPATH_GL20:
8223 case RENDERPATH_CGGL:
8224 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8226 case RENDERPATH_D3D9:
8227 case RENDERPATH_D3D10:
8228 case RENDERPATH_D3D11:
8231 GL_CullFace(r_refdef.view.cullface_back);
8236 R_RenderView_UpdateViewVectors
8239 static void R_RenderView_UpdateViewVectors(void)
8241 // break apart the view matrix into vectors for various purposes
8242 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8243 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8244 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8245 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8246 // make an inverted copy of the view matrix for tracking sprites
8247 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8250 void R_RenderScene(void);
8251 void R_RenderWaterPlanes(void);
8253 static void R_Water_StartFrame(void)
8256 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8257 r_waterstate_waterplane_t *p;
8259 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8262 switch(vid.renderpath)
8264 case RENDERPATH_GL20:
8265 case RENDERPATH_CGGL:
8266 case RENDERPATH_D3D9:
8267 case RENDERPATH_D3D10:
8268 case RENDERPATH_D3D11:
8270 case RENDERPATH_GL13:
8271 case RENDERPATH_GL11:
8275 // set waterwidth and waterheight to the water resolution that will be
8276 // used (often less than the screen resolution for faster rendering)
8277 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8278 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8280 // calculate desired texture sizes
8281 // can't use water if the card does not support the texture size
8282 if (!r_water.integer || r_showsurfaces.integer)
8283 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8284 else if (vid.support.arb_texture_non_power_of_two)
8286 texturewidth = waterwidth;
8287 textureheight = waterheight;
8288 camerawidth = waterwidth;
8289 cameraheight = waterheight;
8293 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8294 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8295 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8296 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8299 // allocate textures as needed
8300 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8302 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8303 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8305 if (p->texture_refraction)
8306 R_FreeTexture(p->texture_refraction);
8307 p->texture_refraction = NULL;
8308 if (p->texture_reflection)
8309 R_FreeTexture(p->texture_reflection);
8310 p->texture_reflection = NULL;
8311 if (p->texture_camera)
8312 R_FreeTexture(p->texture_camera);
8313 p->texture_camera = NULL;
8315 memset(&r_waterstate, 0, sizeof(r_waterstate));
8316 r_waterstate.texturewidth = texturewidth;
8317 r_waterstate.textureheight = textureheight;
8318 r_waterstate.camerawidth = camerawidth;
8319 r_waterstate.cameraheight = cameraheight;
8322 if (r_waterstate.texturewidth)
8324 r_waterstate.enabled = true;
8326 // when doing a reduced render (HDR) we want to use a smaller area
8327 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8328 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8330 // set up variables that will be used in shader setup
8331 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8332 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8333 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8334 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8337 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8338 r_waterstate.numwaterplanes = 0;
8341 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8343 int triangleindex, planeindex;
8350 r_waterstate_waterplane_t *p;
8351 texture_t *t = R_GetCurrentTexture(surface->texture);
8352 cam_ent = t->camera_entity;
8353 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8356 // just use the first triangle with a valid normal for any decisions
8357 VectorClear(normal);
8358 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8360 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8361 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8362 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8363 TriangleNormal(vert[0], vert[1], vert[2], normal);
8364 if (VectorLength2(normal) >= 0.001)
8368 VectorCopy(normal, plane.normal);
8369 VectorNormalize(plane.normal);
8370 plane.dist = DotProduct(vert[0], plane.normal);
8371 PlaneClassify(&plane);
8372 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8374 // skip backfaces (except if nocullface is set)
8375 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8377 VectorNegate(plane.normal, plane.normal);
8379 PlaneClassify(&plane);
8383 // find a matching plane if there is one
8384 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8385 if(p->camera_entity == t->camera_entity)
8386 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8388 if (planeindex >= r_waterstate.maxwaterplanes)
8389 return; // nothing we can do, out of planes
8391 // if this triangle does not fit any known plane rendered this frame, add one
8392 if (planeindex >= r_waterstate.numwaterplanes)
8394 // store the new plane
8395 r_waterstate.numwaterplanes++;
8397 // clear materialflags and pvs
8398 p->materialflags = 0;
8399 p->pvsvalid = false;
8400 p->camera_entity = t->camera_entity;
8402 // merge this surface's materialflags into the waterplane
8403 p->materialflags |= t->currentmaterialflags;
8404 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8406 // merge this surface's PVS into the waterplane
8407 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8408 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8409 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8411 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8417 static void R_Water_ProcessPlanes(void)
8419 r_refdef_view_t originalview;
8420 r_refdef_view_t myview;
8422 r_waterstate_waterplane_t *p;
8425 originalview = r_refdef.view;
8427 // make sure enough textures are allocated
8428 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8430 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8432 if (!p->texture_refraction)
8433 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8434 if (!p->texture_refraction)
8437 else if (p->materialflags & MATERIALFLAG_CAMERA)
8439 if (!p->texture_camera)
8440 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8441 if (!p->texture_camera)
8445 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8447 if (!p->texture_reflection)
8448 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8449 if (!p->texture_reflection)
8455 r_refdef.view = originalview;
8456 r_refdef.view.showdebug = false;
8457 r_refdef.view.width = r_waterstate.waterwidth;
8458 r_refdef.view.height = r_waterstate.waterheight;
8459 r_refdef.view.useclipplane = true;
8460 myview = r_refdef.view;
8461 r_waterstate.renderingscene = true;
8462 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8464 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8466 r_refdef.view = myview;
8467 // render reflected scene and copy into texture
8468 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8469 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8470 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8471 r_refdef.view.clipplane = p->plane;
8472 // reverse the cullface settings for this render
8473 r_refdef.view.cullface_front = GL_FRONT;
8474 r_refdef.view.cullface_back = GL_BACK;
8475 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8477 r_refdef.view.usecustompvs = true;
8479 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8481 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8484 R_ResetViewRendering3D();
8485 R_ClearScreen(r_refdef.fogenabled);
8489 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);
8492 // render the normal view scene and copy into texture
8493 // (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)
8494 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8496 r_waterstate.renderingrefraction = true;
8497 r_refdef.view = myview;
8499 r_refdef.view.clipplane = p->plane;
8500 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8501 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8503 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8505 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8506 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8507 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8508 R_RenderView_UpdateViewVectors();
8509 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8511 r_refdef.view.usecustompvs = true;
8512 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8516 PlaneClassify(&r_refdef.view.clipplane);
8518 R_ResetViewRendering3D();
8519 R_ClearScreen(r_refdef.fogenabled);
8523 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);
8524 r_waterstate.renderingrefraction = false;
8526 else if (p->materialflags & MATERIALFLAG_CAMERA)
8528 r_refdef.view = myview;
8530 r_refdef.view.clipplane = p->plane;
8531 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8532 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8534 r_refdef.view.width = r_waterstate.camerawidth;
8535 r_refdef.view.height = r_waterstate.cameraheight;
8536 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8537 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8539 if(p->camera_entity)
8541 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8542 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8545 // reverse the cullface settings for this render
8546 r_refdef.view.cullface_front = GL_FRONT;
8547 r_refdef.view.cullface_back = GL_BACK;
8548 // also reverse the view matrix
8549 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8550 R_RenderView_UpdateViewVectors();
8551 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8553 r_refdef.view.usecustompvs = true;
8554 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8557 // camera needs no clipplane
8558 r_refdef.view.useclipplane = false;
8560 PlaneClassify(&r_refdef.view.clipplane);
8562 R_ResetViewRendering3D();
8563 R_ClearScreen(r_refdef.fogenabled);
8567 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8568 r_waterstate.renderingrefraction = false;
8572 r_waterstate.renderingscene = false;
8573 r_refdef.view = originalview;
8574 R_ResetViewRendering3D();
8575 R_ClearScreen(r_refdef.fogenabled);
8579 r_refdef.view = originalview;
8580 r_waterstate.renderingscene = false;
8581 Cvar_SetValueQuick(&r_water, 0);
8582 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8586 void R_Bloom_StartFrame(void)
8588 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8590 switch(vid.renderpath)
8592 case RENDERPATH_GL20:
8593 case RENDERPATH_CGGL:
8594 case RENDERPATH_D3D9:
8595 case RENDERPATH_D3D10:
8596 case RENDERPATH_D3D11:
8598 case RENDERPATH_GL13:
8599 case RENDERPATH_GL11:
8603 // set bloomwidth and bloomheight to the bloom resolution that will be
8604 // used (often less than the screen resolution for faster rendering)
8605 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8606 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8607 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8608 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8609 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8611 // calculate desired texture sizes
8612 if (vid.support.arb_texture_non_power_of_two)
8614 screentexturewidth = r_refdef.view.width;
8615 screentextureheight = r_refdef.view.height;
8616 bloomtexturewidth = r_bloomstate.bloomwidth;
8617 bloomtextureheight = r_bloomstate.bloomheight;
8621 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8622 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8623 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8624 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8627 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))
8629 Cvar_SetValueQuick(&r_hdr, 0);
8630 Cvar_SetValueQuick(&r_bloom, 0);
8631 Cvar_SetValueQuick(&r_motionblur, 0);
8632 Cvar_SetValueQuick(&r_damageblur, 0);
8635 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)))
8636 screentexturewidth = screentextureheight = 0;
8637 if (!r_hdr.integer && !r_bloom.integer)
8638 bloomtexturewidth = bloomtextureheight = 0;
8640 // allocate textures as needed
8641 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8643 if (r_bloomstate.texture_screen)
8644 R_FreeTexture(r_bloomstate.texture_screen);
8645 r_bloomstate.texture_screen = NULL;
8646 r_bloomstate.screentexturewidth = screentexturewidth;
8647 r_bloomstate.screentextureheight = screentextureheight;
8648 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8649 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8651 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8653 if (r_bloomstate.texture_bloom)
8654 R_FreeTexture(r_bloomstate.texture_bloom);
8655 r_bloomstate.texture_bloom = NULL;
8656 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8657 r_bloomstate.bloomtextureheight = bloomtextureheight;
8658 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8659 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8662 // when doing a reduced render (HDR) we want to use a smaller area
8663 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8664 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8665 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8666 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8667 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8669 // set up a texcoord array for the full resolution screen image
8670 // (we have to keep this around to copy back during final render)
8671 r_bloomstate.screentexcoord2f[0] = 0;
8672 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8673 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8674 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8675 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8676 r_bloomstate.screentexcoord2f[5] = 0;
8677 r_bloomstate.screentexcoord2f[6] = 0;
8678 r_bloomstate.screentexcoord2f[7] = 0;
8680 // set up a texcoord array for the reduced resolution bloom image
8681 // (which will be additive blended over the screen image)
8682 r_bloomstate.bloomtexcoord2f[0] = 0;
8683 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8684 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8685 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8686 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8687 r_bloomstate.bloomtexcoord2f[5] = 0;
8688 r_bloomstate.bloomtexcoord2f[6] = 0;
8689 r_bloomstate.bloomtexcoord2f[7] = 0;
8691 switch(vid.renderpath)
8693 case RENDERPATH_GL11:
8694 case RENDERPATH_GL13:
8695 case RENDERPATH_GL20:
8696 case RENDERPATH_CGGL:
8698 case RENDERPATH_D3D9:
8699 case RENDERPATH_D3D10:
8700 case RENDERPATH_D3D11:
8703 for (i = 0;i < 4;i++)
8705 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8706 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8707 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8708 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8714 if (r_hdr.integer || r_bloom.integer)
8716 r_bloomstate.enabled = true;
8717 r_bloomstate.hdr = r_hdr.integer != 0;
8720 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);
8723 void R_Bloom_CopyBloomTexture(float colorscale)
8725 r_refdef.stats.bloom++;
8727 // scale down screen texture to the bloom texture size
8729 R_SetViewport(&r_bloomstate.viewport);
8730 GL_BlendFunc(GL_ONE, GL_ZERO);
8731 GL_Color(colorscale, colorscale, colorscale, 1);
8732 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
8733 switch(vid.renderpath)
8735 case RENDERPATH_GL11:
8736 case RENDERPATH_GL13:
8737 case RENDERPATH_GL20:
8738 case RENDERPATH_CGGL:
8739 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8741 case RENDERPATH_D3D9:
8742 case RENDERPATH_D3D10:
8743 case RENDERPATH_D3D11:
8744 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8747 // TODO: do boxfilter scale-down in shader?
8748 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8749 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8750 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8752 // we now have a bloom image in the framebuffer
8753 // copy it into the bloom image texture for later processing
8754 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);
8755 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8758 void R_Bloom_CopyHDRTexture(void)
8760 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);
8761 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8764 void R_Bloom_MakeTexture(void)
8767 float xoffset, yoffset, r, brighten;
8769 r_refdef.stats.bloom++;
8771 R_ResetViewRendering2D();
8773 // we have a bloom image in the framebuffer
8775 R_SetViewport(&r_bloomstate.viewport);
8777 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8780 r = bound(0, r_bloom_colorexponent.value / x, 1);
8781 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8783 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8784 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8785 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8786 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8788 // copy the vertically blurred bloom view to a texture
8789 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);
8790 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8793 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8794 brighten = r_bloom_brighten.value;
8796 brighten *= r_hdr_range.value;
8797 brighten = sqrt(brighten);
8799 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8800 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8802 for (dir = 0;dir < 2;dir++)
8804 // blend on at multiple vertical offsets to achieve a vertical blur
8805 // TODO: do offset blends using GLSL
8806 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8807 GL_BlendFunc(GL_ONE, GL_ZERO);
8808 for (x = -range;x <= range;x++)
8810 if (!dir){xoffset = 0;yoffset = x;}
8811 else {xoffset = x;yoffset = 0;}
8812 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8813 yoffset /= (float)r_bloomstate.bloomtextureheight;
8814 // compute a texcoord array with the specified x and y offset
8815 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8816 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8817 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8818 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8819 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8820 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8821 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8822 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8823 // this r value looks like a 'dot' particle, fading sharply to
8824 // black at the edges
8825 // (probably not realistic but looks good enough)
8826 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8827 //r = brighten/(range*2+1);
8828 r = brighten / (range * 2 + 1);
8830 r *= (1 - x*x/(float)(range*range));
8831 GL_Color(r, r, r, 1);
8832 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8833 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8834 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8835 GL_BlendFunc(GL_ONE, GL_ONE);
8838 // copy the vertically blurred bloom view to a texture
8839 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);
8840 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8844 void R_HDR_RenderBloomTexture(void)
8846 int oldwidth, oldheight;
8847 float oldcolorscale;
8849 oldcolorscale = r_refdef.view.colorscale;
8850 oldwidth = r_refdef.view.width;
8851 oldheight = r_refdef.view.height;
8852 r_refdef.view.width = r_bloomstate.bloomwidth;
8853 r_refdef.view.height = r_bloomstate.bloomheight;
8855 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8856 // TODO: add exposure compensation features
8857 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8859 r_refdef.view.showdebug = false;
8860 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8862 R_ResetViewRendering3D();
8864 R_ClearScreen(r_refdef.fogenabled);
8865 if (r_timereport_active)
8866 R_TimeReport("HDRclear");
8869 if (r_timereport_active)
8870 R_TimeReport("visibility");
8872 // only do secondary renders with HDR if r_hdr is 2 or higher
8873 r_waterstate.numwaterplanes = 0;
8874 if (r_waterstate.enabled && r_hdr.integer >= 2)
8875 R_RenderWaterPlanes();
8877 r_refdef.view.showdebug = true;
8879 r_waterstate.numwaterplanes = 0;
8881 R_ResetViewRendering2D();
8883 R_Bloom_CopyHDRTexture();
8884 R_Bloom_MakeTexture();
8886 // restore the view settings
8887 r_refdef.view.width = oldwidth;
8888 r_refdef.view.height = oldheight;
8889 r_refdef.view.colorscale = oldcolorscale;
8891 R_ResetViewRendering3D();
8893 R_ClearScreen(r_refdef.fogenabled);
8894 if (r_timereport_active)
8895 R_TimeReport("viewclear");
8898 static void R_BlendView(void)
8900 unsigned int permutation;
8901 float uservecs[4][4];
8903 switch (vid.renderpath)
8905 case RENDERPATH_GL20:
8906 case RENDERPATH_CGGL:
8907 case RENDERPATH_D3D9:
8908 case RENDERPATH_D3D10:
8909 case RENDERPATH_D3D11:
8911 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8912 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8913 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8914 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8915 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8917 if (r_bloomstate.texture_screen)
8919 // make sure the buffer is available
8920 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8922 R_ResetViewRendering2D();
8924 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8926 // declare variables
8928 static float avgspeed;
8930 speed = VectorLength(cl.movement_velocity);
8932 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8933 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8935 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8936 speed = bound(0, speed, 1);
8937 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8939 // calculate values into a standard alpha
8940 cl.motionbluralpha = 1 - exp(-
8942 (r_motionblur.value * speed / 80)
8944 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8947 max(0.0001, cl.time - cl.oldtime) // fps independent
8950 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8951 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8953 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8955 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8956 GL_Color(1, 1, 1, cl.motionbluralpha);
8957 switch(vid.renderpath)
8959 case RENDERPATH_GL11:
8960 case RENDERPATH_GL13:
8961 case RENDERPATH_GL20:
8962 case RENDERPATH_CGGL:
8963 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8965 case RENDERPATH_D3D9:
8966 case RENDERPATH_D3D10:
8967 case RENDERPATH_D3D11:
8968 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8971 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8972 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8973 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8977 // copy view into the screen texture
8978 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);
8979 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8981 else if (!r_bloomstate.texture_bloom)
8983 // we may still have to do view tint...
8984 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8986 // apply a color tint to the whole view
8987 R_ResetViewRendering2D();
8988 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8989 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8990 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8991 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8992 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8994 break; // no screen processing, no bloom, skip it
8997 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8999 // render simple bloom effect
9000 // copy the screen and shrink it and darken it for the bloom process
9001 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9002 // make the bloom texture
9003 R_Bloom_MakeTexture();
9006 #if _MSC_VER >= 1400
9007 #define sscanf sscanf_s
9009 memset(uservecs, 0, sizeof(uservecs));
9010 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9011 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9012 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9013 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9015 R_ResetViewRendering2D();
9016 GL_Color(1, 1, 1, 1);
9017 GL_BlendFunc(GL_ONE, GL_ZERO);
9019 switch(vid.renderpath)
9021 case RENDERPATH_GL20:
9022 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9023 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9024 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9025 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9026 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9027 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]);
9028 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9029 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]);
9030 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]);
9031 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]);
9032 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]);
9033 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9034 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9035 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9037 case RENDERPATH_CGGL:
9039 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9040 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9041 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9042 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9043 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9044 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
9045 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9046 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
9047 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
9048 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
9049 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
9050 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9051 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9052 if (r_cg_permutation->fp_BloomColorSubtract ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9055 case RENDERPATH_D3D9:
9057 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9058 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9059 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9060 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9061 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9062 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9063 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9064 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9065 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9066 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9067 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9068 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9069 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9070 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9071 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9074 case RENDERPATH_D3D10:
9075 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9077 case RENDERPATH_D3D11:
9078 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9083 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9084 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9086 case RENDERPATH_GL13:
9087 case RENDERPATH_GL11:
9088 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9090 // apply a color tint to the whole view
9091 R_ResetViewRendering2D();
9092 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9093 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9094 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9095 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9096 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9102 matrix4x4_t r_waterscrollmatrix;
9104 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9106 if (r_refdef.fog_density)
9108 r_refdef.fogcolor[0] = r_refdef.fog_red;
9109 r_refdef.fogcolor[1] = r_refdef.fog_green;
9110 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9112 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9113 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9114 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9115 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9119 VectorCopy(r_refdef.fogcolor, fogvec);
9120 // color.rgb *= ContrastBoost * SceneBrightness;
9121 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9122 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9123 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9124 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9129 void R_UpdateVariables(void)
9133 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9135 r_refdef.farclip = r_farclip_base.value;
9136 if (r_refdef.scene.worldmodel)
9137 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9138 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9140 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9141 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9142 r_refdef.polygonfactor = 0;
9143 r_refdef.polygonoffset = 0;
9144 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9145 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9147 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9148 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9149 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9150 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9151 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9152 if (r_showsurfaces.integer)
9154 r_refdef.scene.rtworld = false;
9155 r_refdef.scene.rtworldshadows = false;
9156 r_refdef.scene.rtdlight = false;
9157 r_refdef.scene.rtdlightshadows = false;
9158 r_refdef.lightmapintensity = 0;
9161 if (gamemode == GAME_NEHAHRA)
9163 if (gl_fogenable.integer)
9165 r_refdef.oldgl_fogenable = true;
9166 r_refdef.fog_density = gl_fogdensity.value;
9167 r_refdef.fog_red = gl_fogred.value;
9168 r_refdef.fog_green = gl_foggreen.value;
9169 r_refdef.fog_blue = gl_fogblue.value;
9170 r_refdef.fog_alpha = 1;
9171 r_refdef.fog_start = 0;
9172 r_refdef.fog_end = gl_skyclip.value;
9173 r_refdef.fog_height = 1<<30;
9174 r_refdef.fog_fadedepth = 128;
9176 else if (r_refdef.oldgl_fogenable)
9178 r_refdef.oldgl_fogenable = false;
9179 r_refdef.fog_density = 0;
9180 r_refdef.fog_red = 0;
9181 r_refdef.fog_green = 0;
9182 r_refdef.fog_blue = 0;
9183 r_refdef.fog_alpha = 0;
9184 r_refdef.fog_start = 0;
9185 r_refdef.fog_end = 0;
9186 r_refdef.fog_height = 1<<30;
9187 r_refdef.fog_fadedepth = 128;
9191 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9192 r_refdef.fog_start = max(0, r_refdef.fog_start);
9193 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9195 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9197 if (r_refdef.fog_density && r_drawfog.integer)
9199 r_refdef.fogenabled = true;
9200 // this is the point where the fog reaches 0.9986 alpha, which we
9201 // consider a good enough cutoff point for the texture
9202 // (0.9986 * 256 == 255.6)
9203 if (r_fog_exp2.integer)
9204 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9206 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9207 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9208 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9209 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9210 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9211 R_BuildFogHeightTexture();
9212 // fog color was already set
9213 // update the fog texture
9214 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)
9215 R_BuildFogTexture();
9216 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9217 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9220 r_refdef.fogenabled = false;
9222 switch(vid.renderpath)
9224 case RENDERPATH_GL20:
9225 case RENDERPATH_CGGL:
9226 case RENDERPATH_D3D9:
9227 case RENDERPATH_D3D10:
9228 case RENDERPATH_D3D11:
9229 if(v_glslgamma.integer && !vid_gammatables_trivial)
9231 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9233 // build GLSL gamma texture
9234 #define RAMPWIDTH 256
9235 unsigned short ramp[RAMPWIDTH * 3];
9236 unsigned char rampbgr[RAMPWIDTH][4];
9239 r_texture_gammaramps_serial = vid_gammatables_serial;
9241 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9242 for(i = 0; i < RAMPWIDTH; ++i)
9244 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9245 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9246 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9249 if (r_texture_gammaramps)
9251 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9255 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9261 // remove GLSL gamma texture
9264 case RENDERPATH_GL13:
9265 case RENDERPATH_GL11:
9270 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9271 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9277 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9278 if( scenetype != r_currentscenetype ) {
9279 // store the old scenetype
9280 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9281 r_currentscenetype = scenetype;
9282 // move in the new scene
9283 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9292 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9294 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9295 if( scenetype == r_currentscenetype ) {
9296 return &r_refdef.scene;
9298 return &r_scenes_store[ scenetype ];
9307 void R_RenderView(void)
9309 if (r_timereport_active)
9310 R_TimeReport("start");
9311 r_textureframe++; // used only by R_GetCurrentTexture
9312 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9314 if (!r_drawentities.integer)
9315 r_refdef.scene.numentities = 0;
9317 R_AnimCache_ClearCache();
9318 R_FrameData_NewFrame();
9320 if (r_refdef.view.isoverlay)
9322 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9323 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9324 R_TimeReport("depthclear");
9326 r_refdef.view.showdebug = false;
9328 r_waterstate.enabled = false;
9329 r_waterstate.numwaterplanes = 0;
9337 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9338 return; //Host_Error ("R_RenderView: NULL worldmodel");
9340 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9342 R_RenderView_UpdateViewVectors();
9344 R_Shadow_UpdateWorldLightSelection();
9346 R_Bloom_StartFrame();
9347 R_Water_StartFrame();
9350 if (r_timereport_active)
9351 R_TimeReport("viewsetup");
9353 R_ResetViewRendering3D();
9355 if (r_refdef.view.clear || r_refdef.fogenabled)
9357 R_ClearScreen(r_refdef.fogenabled);
9358 if (r_timereport_active)
9359 R_TimeReport("viewclear");
9361 r_refdef.view.clear = true;
9363 // this produces a bloom texture to be used in R_BlendView() later
9364 if (r_hdr.integer && r_bloomstate.bloomwidth)
9366 R_HDR_RenderBloomTexture();
9367 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9368 r_textureframe++; // used only by R_GetCurrentTexture
9371 r_refdef.view.showdebug = true;
9374 if (r_timereport_active)
9375 R_TimeReport("visibility");
9377 r_waterstate.numwaterplanes = 0;
9378 if (r_waterstate.enabled)
9379 R_RenderWaterPlanes();
9382 r_waterstate.numwaterplanes = 0;
9385 if (r_timereport_active)
9386 R_TimeReport("blendview");
9388 GL_Scissor(0, 0, vid.width, vid.height);
9389 GL_ScissorTest(false);
9393 void R_RenderWaterPlanes(void)
9395 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9397 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9398 if (r_timereport_active)
9399 R_TimeReport("waterworld");
9402 // don't let sound skip if going slow
9403 if (r_refdef.scene.extraupdate)
9406 R_DrawModelsAddWaterPlanes();
9407 if (r_timereport_active)
9408 R_TimeReport("watermodels");
9410 if (r_waterstate.numwaterplanes)
9412 R_Water_ProcessPlanes();
9413 if (r_timereport_active)
9414 R_TimeReport("waterscenes");
9418 extern void R_DrawLightningBeams (void);
9419 extern void VM_CL_AddPolygonsToMeshQueue (void);
9420 extern void R_DrawPortals (void);
9421 extern cvar_t cl_locs_show;
9422 static void R_DrawLocs(void);
9423 static void R_DrawEntityBBoxes(void);
9424 static void R_DrawModelDecals(void);
9425 extern void R_DrawModelShadows(void);
9426 extern void R_DrawModelShadowMaps(void);
9427 extern cvar_t cl_decals_newsystem;
9428 extern qboolean r_shadow_usingdeferredprepass;
9429 void R_RenderScene(void)
9431 qboolean shadowmapping = false;
9433 if (r_timereport_active)
9434 R_TimeReport("beginscene");
9436 r_refdef.stats.renders++;
9440 // don't let sound skip if going slow
9441 if (r_refdef.scene.extraupdate)
9444 R_MeshQueue_BeginScene();
9448 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);
9450 if (r_timereport_active)
9451 R_TimeReport("skystartframe");
9453 if (cl.csqc_vidvars.drawworld)
9455 // don't let sound skip if going slow
9456 if (r_refdef.scene.extraupdate)
9459 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9461 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9462 if (r_timereport_active)
9463 R_TimeReport("worldsky");
9466 if (R_DrawBrushModelsSky() && r_timereport_active)
9467 R_TimeReport("bmodelsky");
9469 if (skyrendermasked && skyrenderlater)
9471 // we have to force off the water clipping plane while rendering sky
9475 if (r_timereport_active)
9476 R_TimeReport("sky");
9480 R_AnimCache_CacheVisibleEntities();
9481 if (r_timereport_active)
9482 R_TimeReport("animation");
9484 R_Shadow_PrepareLights();
9485 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9486 R_Shadow_PrepareModelShadows();
9487 if (r_timereport_active)
9488 R_TimeReport("preparelights");
9490 if (R_Shadow_ShadowMappingEnabled())
9491 shadowmapping = true;
9493 if (r_shadow_usingdeferredprepass)
9494 R_Shadow_DrawPrepass();
9496 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9498 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9499 if (r_timereport_active)
9500 R_TimeReport("worlddepth");
9502 if (r_depthfirst.integer >= 2)
9504 R_DrawModelsDepth();
9505 if (r_timereport_active)
9506 R_TimeReport("modeldepth");
9509 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9511 R_DrawModelShadowMaps();
9512 R_ResetViewRendering3D();
9513 // don't let sound skip if going slow
9514 if (r_refdef.scene.extraupdate)
9518 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9520 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9521 if (r_timereport_active)
9522 R_TimeReport("world");
9525 // don't let sound skip if going slow
9526 if (r_refdef.scene.extraupdate)
9530 if (r_timereport_active)
9531 R_TimeReport("models");
9533 // don't let sound skip if going slow
9534 if (r_refdef.scene.extraupdate)
9537 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9539 R_DrawModelShadows();
9540 R_ResetViewRendering3D();
9541 // don't let sound skip if going slow
9542 if (r_refdef.scene.extraupdate)
9546 if (!r_shadow_usingdeferredprepass)
9548 R_Shadow_DrawLights();
9549 if (r_timereport_active)
9550 R_TimeReport("rtlights");
9553 // don't let sound skip if going slow
9554 if (r_refdef.scene.extraupdate)
9557 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9559 R_DrawModelShadows();
9560 R_ResetViewRendering3D();
9561 // don't let sound skip if going slow
9562 if (r_refdef.scene.extraupdate)
9566 if (cl.csqc_vidvars.drawworld)
9568 if (cl_decals_newsystem.integer)
9570 R_DrawModelDecals();
9571 if (r_timereport_active)
9572 R_TimeReport("modeldecals");
9577 if (r_timereport_active)
9578 R_TimeReport("decals");
9582 if (r_timereport_active)
9583 R_TimeReport("particles");
9586 if (r_timereport_active)
9587 R_TimeReport("explosions");
9589 R_DrawLightningBeams();
9590 if (r_timereport_active)
9591 R_TimeReport("lightning");
9594 VM_CL_AddPolygonsToMeshQueue();
9596 if (r_refdef.view.showdebug)
9598 if (cl_locs_show.integer)
9601 if (r_timereport_active)
9602 R_TimeReport("showlocs");
9605 if (r_drawportals.integer)
9608 if (r_timereport_active)
9609 R_TimeReport("portals");
9612 if (r_showbboxes.value > 0)
9614 R_DrawEntityBBoxes();
9615 if (r_timereport_active)
9616 R_TimeReport("bboxes");
9620 R_MeshQueue_RenderTransparent();
9621 if (r_timereport_active)
9622 R_TimeReport("drawtrans");
9624 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))
9626 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9627 if (r_timereport_active)
9628 R_TimeReport("worlddebug");
9629 R_DrawModelsDebug();
9630 if (r_timereport_active)
9631 R_TimeReport("modeldebug");
9634 if (cl.csqc_vidvars.drawworld)
9636 R_Shadow_DrawCoronas();
9637 if (r_timereport_active)
9638 R_TimeReport("coronas");
9641 // don't let sound skip if going slow
9642 if (r_refdef.scene.extraupdate)
9645 R_ResetViewRendering2D();
9648 static const unsigned short bboxelements[36] =
9658 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9661 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9663 RSurf_ActiveWorldEntity();
9665 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9666 GL_DepthMask(false);
9667 GL_DepthRange(0, 1);
9668 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9669 R_Mesh_ResetTextureState();
9671 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9672 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9673 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9674 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9675 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9676 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9677 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9678 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9679 R_FillColors(color4f, 8, cr, cg, cb, ca);
9680 if (r_refdef.fogenabled)
9682 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9684 f1 = RSurf_FogVertex(v);
9686 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9687 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9688 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9691 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9692 R_Mesh_ResetTextureState();
9693 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9694 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9697 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9701 prvm_edict_t *edict;
9702 prvm_prog_t *prog_save = prog;
9704 // this function draws bounding boxes of server entities
9708 GL_CullFace(GL_NONE);
9709 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9713 for (i = 0;i < numsurfaces;i++)
9715 edict = PRVM_EDICT_NUM(surfacelist[i]);
9716 switch ((int)edict->fields.server->solid)
9718 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9719 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9720 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9721 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9722 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9723 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9725 color[3] *= r_showbboxes.value;
9726 color[3] = bound(0, color[3], 1);
9727 GL_DepthTest(!r_showdisabledepthtest.integer);
9728 GL_CullFace(r_refdef.view.cullface_front);
9729 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9735 static void R_DrawEntityBBoxes(void)
9738 prvm_edict_t *edict;
9740 prvm_prog_t *prog_save = prog;
9742 // this function draws bounding boxes of server entities
9748 for (i = 0;i < prog->num_edicts;i++)
9750 edict = PRVM_EDICT_NUM(i);
9751 if (edict->priv.server->free)
9753 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9754 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9756 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9758 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9759 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9765 static const int nomodelelement3i[24] =
9777 static const unsigned short nomodelelement3s[24] =
9789 static const float nomodelvertex3f[6*3] =
9799 static const float nomodelcolor4f[6*4] =
9801 0.0f, 0.0f, 0.5f, 1.0f,
9802 0.0f, 0.0f, 0.5f, 1.0f,
9803 0.0f, 0.5f, 0.0f, 1.0f,
9804 0.0f, 0.5f, 0.0f, 1.0f,
9805 0.5f, 0.0f, 0.0f, 1.0f,
9806 0.5f, 0.0f, 0.0f, 1.0f
9809 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9815 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);
9817 // this is only called once per entity so numsurfaces is always 1, and
9818 // surfacelist is always {0}, so this code does not handle batches
9820 if (rsurface.ent_flags & RENDER_ADDITIVE)
9822 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9823 GL_DepthMask(false);
9825 else if (rsurface.colormod[3] < 1)
9827 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9828 GL_DepthMask(false);
9832 GL_BlendFunc(GL_ONE, GL_ZERO);
9835 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9836 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9837 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9838 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9839 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9840 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9841 for (i = 0, c = color4f;i < 6;i++, c += 4)
9843 c[0] *= rsurface.colormod[0];
9844 c[1] *= rsurface.colormod[1];
9845 c[2] *= rsurface.colormod[2];
9846 c[3] *= rsurface.colormod[3];
9848 if (r_refdef.fogenabled)
9850 for (i = 0, c = color4f;i < 6;i++, c += 4)
9852 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9854 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9855 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9856 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9859 R_Mesh_ResetTextureState();
9860 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9861 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9864 void R_DrawNoModel(entity_render_t *ent)
9867 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9868 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9869 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9871 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9874 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9876 vec3_t right1, right2, diff, normal;
9878 VectorSubtract (org2, org1, normal);
9880 // calculate 'right' vector for start
9881 VectorSubtract (r_refdef.view.origin, org1, diff);
9882 CrossProduct (normal, diff, right1);
9883 VectorNormalize (right1);
9885 // calculate 'right' vector for end
9886 VectorSubtract (r_refdef.view.origin, org2, diff);
9887 CrossProduct (normal, diff, right2);
9888 VectorNormalize (right2);
9890 vert[ 0] = org1[0] + width * right1[0];
9891 vert[ 1] = org1[1] + width * right1[1];
9892 vert[ 2] = org1[2] + width * right1[2];
9893 vert[ 3] = org1[0] - width * right1[0];
9894 vert[ 4] = org1[1] - width * right1[1];
9895 vert[ 5] = org1[2] - width * right1[2];
9896 vert[ 6] = org2[0] - width * right2[0];
9897 vert[ 7] = org2[1] - width * right2[1];
9898 vert[ 8] = org2[2] - width * right2[2];
9899 vert[ 9] = org2[0] + width * right2[0];
9900 vert[10] = org2[1] + width * right2[1];
9901 vert[11] = org2[2] + width * right2[2];
9904 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)
9906 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9907 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9908 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9909 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9910 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9911 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9912 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9913 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9914 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9915 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9916 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9917 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9920 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9925 VectorSet(v, x, y, z);
9926 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9927 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9929 if (i == mesh->numvertices)
9931 if (mesh->numvertices < mesh->maxvertices)
9933 VectorCopy(v, vertex3f);
9934 mesh->numvertices++;
9936 return mesh->numvertices;
9942 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9946 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9947 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9948 e = mesh->element3i + mesh->numtriangles * 3;
9949 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9951 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9952 if (mesh->numtriangles < mesh->maxtriangles)
9957 mesh->numtriangles++;
9959 element[1] = element[2];
9963 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9967 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9968 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9969 e = mesh->element3i + mesh->numtriangles * 3;
9970 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9972 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9973 if (mesh->numtriangles < mesh->maxtriangles)
9978 mesh->numtriangles++;
9980 element[1] = element[2];
9984 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9985 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9987 int planenum, planenum2;
9990 mplane_t *plane, *plane2;
9992 double temppoints[2][256*3];
9993 // figure out how large a bounding box we need to properly compute this brush
9995 for (w = 0;w < numplanes;w++)
9996 maxdist = max(maxdist, fabs(planes[w].dist));
9997 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9998 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9999 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10003 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10004 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10006 if (planenum2 == planenum)
10008 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);
10011 if (tempnumpoints < 3)
10013 // generate elements forming a triangle fan for this polygon
10014 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10018 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)
10020 texturelayer_t *layer;
10021 layer = t->currentlayers + t->currentnumlayers++;
10022 layer->type = type;
10023 layer->depthmask = depthmask;
10024 layer->blendfunc1 = blendfunc1;
10025 layer->blendfunc2 = blendfunc2;
10026 layer->texture = texture;
10027 layer->texmatrix = *matrix;
10028 layer->color[0] = r;
10029 layer->color[1] = g;
10030 layer->color[2] = b;
10031 layer->color[3] = a;
10034 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10036 if(parms[0] == 0 && parms[1] == 0)
10038 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10039 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10044 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10047 index = parms[2] + r_refdef.scene.time * parms[3];
10048 index -= floor(index);
10049 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10052 case Q3WAVEFUNC_NONE:
10053 case Q3WAVEFUNC_NOISE:
10054 case Q3WAVEFUNC_COUNT:
10057 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10058 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10059 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10060 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10061 case Q3WAVEFUNC_TRIANGLE:
10063 f = index - floor(index);
10066 else if (index < 2)
10068 else if (index < 3)
10074 f = parms[0] + parms[1] * f;
10075 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10076 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10080 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10085 matrix4x4_t matrix, temp;
10086 switch(tcmod->tcmod)
10088 case Q3TCMOD_COUNT:
10090 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10091 matrix = r_waterscrollmatrix;
10093 matrix = identitymatrix;
10095 case Q3TCMOD_ENTITYTRANSLATE:
10096 // this is used in Q3 to allow the gamecode to control texcoord
10097 // scrolling on the entity, which is not supported in darkplaces yet.
10098 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10100 case Q3TCMOD_ROTATE:
10101 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10102 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10103 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10105 case Q3TCMOD_SCALE:
10106 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10108 case Q3TCMOD_SCROLL:
10109 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10111 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10112 w = (int) tcmod->parms[0];
10113 h = (int) tcmod->parms[1];
10114 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10116 idx = (int) floor(f * w * h);
10117 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10119 case Q3TCMOD_STRETCH:
10120 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10121 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10123 case Q3TCMOD_TRANSFORM:
10124 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10125 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10126 VectorSet(tcmat + 6, 0 , 0 , 1);
10127 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10128 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10130 case Q3TCMOD_TURBULENT:
10131 // this is handled in the RSurf_PrepareVertices function
10132 matrix = identitymatrix;
10136 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10139 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10141 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10142 char name[MAX_QPATH];
10143 skinframe_t *skinframe;
10144 unsigned char pixels[296*194];
10145 strlcpy(cache->name, skinname, sizeof(cache->name));
10146 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10147 if (developer_loading.integer)
10148 Con_Printf("loading %s\n", name);
10149 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10150 if (!skinframe || !skinframe->base)
10153 fs_offset_t filesize;
10155 f = FS_LoadFile(name, tempmempool, true, &filesize);
10158 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10159 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10163 cache->skinframe = skinframe;
10166 texture_t *R_GetCurrentTexture(texture_t *t)
10169 const entity_render_t *ent = rsurface.entity;
10170 dp_model_t *model = ent->model;
10171 q3shaderinfo_layer_tcmod_t *tcmod;
10173 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10174 return t->currentframe;
10175 t->update_lastrenderframe = r_textureframe;
10176 t->update_lastrenderentity = (void *)ent;
10178 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10179 t->camera_entity = ent->entitynumber;
10181 t->camera_entity = 0;
10183 // switch to an alternate material if this is a q1bsp animated material
10185 texture_t *texture = t;
10186 int s = rsurface.ent_skinnum;
10187 if ((unsigned int)s >= (unsigned int)model->numskins)
10189 if (model->skinscenes)
10191 if (model->skinscenes[s].framecount > 1)
10192 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10194 s = model->skinscenes[s].firstframe;
10197 t = t + s * model->num_surfaces;
10200 // use an alternate animation if the entity's frame is not 0,
10201 // and only if the texture has an alternate animation
10202 if (rsurface.ent_alttextures && t->anim_total[1])
10203 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10205 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10207 texture->currentframe = t;
10210 // update currentskinframe to be a qw skin or animation frame
10211 if (rsurface.ent_qwskin >= 0)
10213 i = rsurface.ent_qwskin;
10214 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10216 r_qwskincache_size = cl.maxclients;
10218 Mem_Free(r_qwskincache);
10219 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10221 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10222 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10223 t->currentskinframe = r_qwskincache[i].skinframe;
10224 if (t->currentskinframe == NULL)
10225 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10227 else if (t->numskinframes >= 2)
10228 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10229 if (t->backgroundnumskinframes >= 2)
10230 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10232 t->currentmaterialflags = t->basematerialflags;
10233 t->currentalpha = rsurface.colormod[3];
10234 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10235 t->currentalpha *= r_wateralpha.value;
10236 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10237 t->currentalpha *= t->r_water_wateralpha;
10238 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10239 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10240 if (!(rsurface.ent_flags & RENDER_LIGHT))
10241 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10242 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10244 // pick a model lighting mode
10245 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10246 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10248 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10250 if (rsurface.ent_flags & RENDER_ADDITIVE)
10251 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10252 else if (t->currentalpha < 1)
10253 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10254 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10255 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10256 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10257 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10258 if (t->backgroundnumskinframes)
10259 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10260 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10262 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10263 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10266 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10267 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10268 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10270 // there is no tcmod
10271 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10273 t->currenttexmatrix = r_waterscrollmatrix;
10274 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10276 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10278 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10279 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10282 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10283 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10284 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10285 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10287 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10288 if (t->currentskinframe->qpixels)
10289 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10290 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10291 if (!t->basetexture)
10292 t->basetexture = r_texture_notexture;
10293 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10294 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10295 t->nmaptexture = t->currentskinframe->nmap;
10296 if (!t->nmaptexture)
10297 t->nmaptexture = r_texture_blanknormalmap;
10298 t->glosstexture = r_texture_black;
10299 t->glowtexture = t->currentskinframe->glow;
10300 t->fogtexture = t->currentskinframe->fog;
10301 t->reflectmasktexture = t->currentskinframe->reflect;
10302 if (t->backgroundnumskinframes)
10304 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10305 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10306 t->backgroundglosstexture = r_texture_black;
10307 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10308 if (!t->backgroundnmaptexture)
10309 t->backgroundnmaptexture = r_texture_blanknormalmap;
10313 t->backgroundbasetexture = r_texture_white;
10314 t->backgroundnmaptexture = r_texture_blanknormalmap;
10315 t->backgroundglosstexture = r_texture_black;
10316 t->backgroundglowtexture = NULL;
10318 t->specularpower = r_shadow_glossexponent.value;
10319 // TODO: store reference values for these in the texture?
10320 t->specularscale = 0;
10321 if (r_shadow_gloss.integer > 0)
10323 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10325 if (r_shadow_glossintensity.value > 0)
10327 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10328 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10329 t->specularscale = r_shadow_glossintensity.value;
10332 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10334 t->glosstexture = r_texture_white;
10335 t->backgroundglosstexture = r_texture_white;
10336 t->specularscale = r_shadow_gloss2intensity.value;
10337 t->specularpower = r_shadow_gloss2exponent.value;
10340 t->specularscale *= t->specularscalemod;
10341 t->specularpower *= t->specularpowermod;
10343 // lightmaps mode looks bad with dlights using actual texturing, so turn
10344 // off the colormap and glossmap, but leave the normalmap on as it still
10345 // accurately represents the shading involved
10346 if (gl_lightmaps.integer)
10348 t->basetexture = r_texture_grey128;
10349 t->pantstexture = r_texture_black;
10350 t->shirttexture = r_texture_black;
10351 t->nmaptexture = r_texture_blanknormalmap;
10352 t->glosstexture = r_texture_black;
10353 t->glowtexture = NULL;
10354 t->fogtexture = NULL;
10355 t->reflectmasktexture = NULL;
10356 t->backgroundbasetexture = NULL;
10357 t->backgroundnmaptexture = r_texture_blanknormalmap;
10358 t->backgroundglosstexture = r_texture_black;
10359 t->backgroundglowtexture = NULL;
10360 t->specularscale = 0;
10361 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10364 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10365 VectorClear(t->dlightcolor);
10366 t->currentnumlayers = 0;
10367 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10369 int blendfunc1, blendfunc2;
10370 qboolean depthmask;
10371 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10373 blendfunc1 = GL_SRC_ALPHA;
10374 blendfunc2 = GL_ONE;
10376 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10378 blendfunc1 = GL_SRC_ALPHA;
10379 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10381 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10383 blendfunc1 = t->customblendfunc[0];
10384 blendfunc2 = t->customblendfunc[1];
10388 blendfunc1 = GL_ONE;
10389 blendfunc2 = GL_ZERO;
10391 // don't colormod evilblend textures
10392 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10393 VectorSet(t->lightmapcolor, 1, 1, 1);
10394 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10395 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10397 // fullbright is not affected by r_refdef.lightmapintensity
10398 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]);
10399 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10400 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]);
10401 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10402 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]);
10406 vec3_t ambientcolor;
10408 // set the color tint used for lights affecting this surface
10409 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10411 // q3bsp has no lightmap updates, so the lightstylevalue that
10412 // would normally be baked into the lightmap must be
10413 // applied to the color
10414 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10415 if (model->type == mod_brushq3)
10416 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10417 colorscale *= r_refdef.lightmapintensity;
10418 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10419 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10420 // basic lit geometry
10421 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]);
10422 // add pants/shirt if needed
10423 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10424 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]);
10425 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10426 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]);
10427 // now add ambient passes if needed
10428 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10430 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]);
10431 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10432 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]);
10433 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10434 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]);
10437 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10438 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]);
10439 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10441 // if this is opaque use alpha blend which will darken the earlier
10444 // if this is an alpha blended material, all the earlier passes
10445 // were darkened by fog already, so we only need to add the fog
10446 // color ontop through the fog mask texture
10448 // if this is an additive blended material, all the earlier passes
10449 // were darkened by fog already, and we should not add fog color
10450 // (because the background was not darkened, there is no fog color
10451 // that was lost behind it).
10452 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]);
10456 return t->currentframe;
10459 rsurfacestate_t rsurface;
10461 void R_Mesh_ResizeArrays(int newvertices)
10463 unsigned char *base;
10465 if (rsurface.array_size >= newvertices)
10467 if (rsurface.array_base)
10468 Mem_Free(rsurface.array_base);
10469 rsurface.array_size = (newvertices + 1023) & ~1023;
10471 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10472 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10473 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10474 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10475 size += rsurface.array_size * sizeof(float[3]);
10476 size += rsurface.array_size * sizeof(float[3]);
10477 size += rsurface.array_size * sizeof(float[3]);
10478 size += rsurface.array_size * sizeof(float[3]);
10479 size += rsurface.array_size * sizeof(float[3]);
10480 size += rsurface.array_size * sizeof(float[3]);
10481 size += rsurface.array_size * sizeof(float[3]);
10482 size += rsurface.array_size * sizeof(float[3]);
10483 size += rsurface.array_size * sizeof(float[4]);
10484 size += rsurface.array_size * sizeof(float[2]);
10485 size += rsurface.array_size * sizeof(float[2]);
10486 size += rsurface.array_size * sizeof(float[4]);
10487 size += rsurface.array_size * sizeof(int[3]);
10488 size += rsurface.array_size * sizeof(unsigned short[3]);
10489 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10490 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10491 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10492 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10493 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10494 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10495 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10496 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10497 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10498 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10499 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10500 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10501 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10502 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10503 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10504 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10505 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10506 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10507 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10510 void RSurf_ActiveWorldEntity(void)
10512 dp_model_t *model = r_refdef.scene.worldmodel;
10513 //if (rsurface.entity == r_refdef.scene.worldentity)
10515 rsurface.entity = r_refdef.scene.worldentity;
10516 rsurface.skeleton = NULL;
10517 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10518 rsurface.ent_skinnum = 0;
10519 rsurface.ent_qwskin = -1;
10520 rsurface.ent_shadertime = 0;
10521 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10522 if (rsurface.array_size < model->surfmesh.num_vertices)
10523 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10524 rsurface.matrix = identitymatrix;
10525 rsurface.inversematrix = identitymatrix;
10526 rsurface.matrixscale = 1;
10527 rsurface.inversematrixscale = 1;
10528 R_EntityMatrix(&identitymatrix);
10529 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10530 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10531 rsurface.fograngerecip = r_refdef.fograngerecip;
10532 rsurface.fogheightfade = r_refdef.fogheightfade;
10533 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10534 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10535 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10536 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10537 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10538 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10539 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10540 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10541 rsurface.colormod[3] = 1;
10542 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);
10543 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10544 rsurface.frameblend[0].lerp = 1;
10545 rsurface.ent_alttextures = false;
10546 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10547 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10548 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10549 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10550 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10551 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10552 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10553 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10554 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10555 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10556 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10557 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10558 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10559 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10560 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10561 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10562 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10563 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10564 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10565 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10566 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10567 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10568 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10569 rsurface.modelelement3i = model->surfmesh.data_element3i;
10570 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10571 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10572 rsurface.modelelement3s = model->surfmesh.data_element3s;
10573 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10574 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10575 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10576 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10577 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10578 rsurface.modelsurfaces = model->data_surfaces;
10579 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10580 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10581 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10582 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10583 rsurface.modelgeneratedvertex = false;
10584 rsurface.batchgeneratedvertex = false;
10585 rsurface.batchfirstvertex = 0;
10586 rsurface.batchnumvertices = 0;
10587 rsurface.batchfirsttriangle = 0;
10588 rsurface.batchnumtriangles = 0;
10589 rsurface.batchvertex3f = NULL;
10590 rsurface.batchvertex3f_vertexbuffer = NULL;
10591 rsurface.batchvertex3f_bufferoffset = 0;
10592 rsurface.batchsvector3f = NULL;
10593 rsurface.batchsvector3f_vertexbuffer = NULL;
10594 rsurface.batchsvector3f_bufferoffset = 0;
10595 rsurface.batchtvector3f = NULL;
10596 rsurface.batchtvector3f_vertexbuffer = NULL;
10597 rsurface.batchtvector3f_bufferoffset = 0;
10598 rsurface.batchnormal3f = NULL;
10599 rsurface.batchnormal3f_vertexbuffer = NULL;
10600 rsurface.batchnormal3f_bufferoffset = 0;
10601 rsurface.batchlightmapcolor4f = NULL;
10602 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10603 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10604 rsurface.batchtexcoordtexture2f = NULL;
10605 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10606 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10607 rsurface.batchtexcoordlightmap2f = NULL;
10608 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10609 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10610 rsurface.batchvertexmesh = NULL;
10611 rsurface.batchvertexmeshbuffer = NULL;
10612 rsurface.batchvertexposition = NULL;
10613 rsurface.batchvertexpositionbuffer = NULL;
10614 rsurface.batchelement3i = NULL;
10615 rsurface.batchelement3i_indexbuffer = NULL;
10616 rsurface.batchelement3i_bufferoffset = 0;
10617 rsurface.batchelement3s = NULL;
10618 rsurface.batchelement3s_indexbuffer = NULL;
10619 rsurface.batchelement3s_bufferoffset = 0;
10620 rsurface.passcolor4f = NULL;
10621 rsurface.passcolor4f_vertexbuffer = NULL;
10622 rsurface.passcolor4f_bufferoffset = 0;
10625 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10627 dp_model_t *model = ent->model;
10628 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10630 rsurface.entity = (entity_render_t *)ent;
10631 rsurface.skeleton = ent->skeleton;
10632 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10633 rsurface.ent_skinnum = ent->skinnum;
10634 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;
10635 rsurface.ent_shadertime = ent->shadertime;
10636 rsurface.ent_flags = ent->flags;
10637 if (rsurface.array_size < model->surfmesh.num_vertices)
10638 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10639 rsurface.matrix = ent->matrix;
10640 rsurface.inversematrix = ent->inversematrix;
10641 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10642 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10643 R_EntityMatrix(&rsurface.matrix);
10644 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10645 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10646 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10647 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10648 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10649 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10650 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10651 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10652 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10653 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10654 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10655 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10656 rsurface.colormod[3] = ent->alpha;
10657 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10658 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10659 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10660 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10661 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10662 if (ent->model->brush.submodel && !prepass)
10664 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10665 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10667 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10669 if (ent->animcache_vertex3f && !r_framedata_failed)
10671 rsurface.modelvertex3f = ent->animcache_vertex3f;
10672 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10673 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10674 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10675 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10676 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10677 rsurface.modelvertexposition = ent->animcache_vertexposition;
10678 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10680 else if (wanttangents)
10682 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10683 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10684 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10685 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10686 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10687 rsurface.modelvertexmesh = NULL;
10688 rsurface.modelvertexmeshbuffer = NULL;
10689 rsurface.modelvertexposition = NULL;
10690 rsurface.modelvertexpositionbuffer = NULL;
10692 else if (wantnormals)
10694 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10695 rsurface.modelsvector3f = NULL;
10696 rsurface.modeltvector3f = NULL;
10697 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10698 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10699 rsurface.modelvertexmesh = NULL;
10700 rsurface.modelvertexmeshbuffer = NULL;
10701 rsurface.modelvertexposition = NULL;
10702 rsurface.modelvertexpositionbuffer = NULL;
10706 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10707 rsurface.modelsvector3f = NULL;
10708 rsurface.modeltvector3f = NULL;
10709 rsurface.modelnormal3f = NULL;
10710 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10711 rsurface.modelvertexmesh = NULL;
10712 rsurface.modelvertexmeshbuffer = NULL;
10713 rsurface.modelvertexposition = NULL;
10714 rsurface.modelvertexpositionbuffer = NULL;
10716 rsurface.modelvertex3f_vertexbuffer = 0;
10717 rsurface.modelvertex3f_bufferoffset = 0;
10718 rsurface.modelsvector3f_vertexbuffer = 0;
10719 rsurface.modelsvector3f_bufferoffset = 0;
10720 rsurface.modeltvector3f_vertexbuffer = 0;
10721 rsurface.modeltvector3f_bufferoffset = 0;
10722 rsurface.modelnormal3f_vertexbuffer = 0;
10723 rsurface.modelnormal3f_bufferoffset = 0;
10724 rsurface.modelgeneratedvertex = true;
10728 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10729 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10730 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10731 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10732 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10733 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10734 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10735 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10736 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10737 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10738 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10739 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10740 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10741 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10742 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10743 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10744 rsurface.modelgeneratedvertex = false;
10746 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10747 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10748 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10749 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10750 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10751 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10752 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10753 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10754 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10755 rsurface.modelelement3i = model->surfmesh.data_element3i;
10756 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10757 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10758 rsurface.modelelement3s = model->surfmesh.data_element3s;
10759 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10760 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10761 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10762 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10763 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10764 rsurface.modelsurfaces = model->data_surfaces;
10765 rsurface.batchgeneratedvertex = false;
10766 rsurface.batchfirstvertex = 0;
10767 rsurface.batchnumvertices = 0;
10768 rsurface.batchfirsttriangle = 0;
10769 rsurface.batchnumtriangles = 0;
10770 rsurface.batchvertex3f = NULL;
10771 rsurface.batchvertex3f_vertexbuffer = NULL;
10772 rsurface.batchvertex3f_bufferoffset = 0;
10773 rsurface.batchsvector3f = NULL;
10774 rsurface.batchsvector3f_vertexbuffer = NULL;
10775 rsurface.batchsvector3f_bufferoffset = 0;
10776 rsurface.batchtvector3f = NULL;
10777 rsurface.batchtvector3f_vertexbuffer = NULL;
10778 rsurface.batchtvector3f_bufferoffset = 0;
10779 rsurface.batchnormal3f = NULL;
10780 rsurface.batchnormal3f_vertexbuffer = NULL;
10781 rsurface.batchnormal3f_bufferoffset = 0;
10782 rsurface.batchlightmapcolor4f = NULL;
10783 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10784 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10785 rsurface.batchtexcoordtexture2f = NULL;
10786 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10787 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10788 rsurface.batchtexcoordlightmap2f = NULL;
10789 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10790 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10791 rsurface.batchvertexmesh = NULL;
10792 rsurface.batchvertexmeshbuffer = NULL;
10793 rsurface.batchvertexposition = NULL;
10794 rsurface.batchvertexpositionbuffer = NULL;
10795 rsurface.batchelement3i = NULL;
10796 rsurface.batchelement3i_indexbuffer = NULL;
10797 rsurface.batchelement3i_bufferoffset = 0;
10798 rsurface.batchelement3s = NULL;
10799 rsurface.batchelement3s_indexbuffer = NULL;
10800 rsurface.batchelement3s_bufferoffset = 0;
10801 rsurface.passcolor4f = NULL;
10802 rsurface.passcolor4f_vertexbuffer = NULL;
10803 rsurface.passcolor4f_bufferoffset = 0;
10806 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)
10810 rsurface.entity = r_refdef.scene.worldentity;
10811 rsurface.skeleton = NULL;
10812 rsurface.ent_skinnum = 0;
10813 rsurface.ent_qwskin = -1;
10814 rsurface.ent_shadertime = shadertime;
10815 rsurface.ent_flags = entflags;
10816 rsurface.modelnumvertices = numvertices;
10817 rsurface.modelnumtriangles = numtriangles;
10818 if (rsurface.array_size < rsurface.modelnumvertices)
10819 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10820 rsurface.matrix = *matrix;
10821 rsurface.inversematrix = *inversematrix;
10822 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10823 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10824 R_EntityMatrix(&rsurface.matrix);
10825 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10826 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10827 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10828 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10829 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10830 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10831 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10832 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10833 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10834 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10835 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10836 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10837 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);
10838 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10839 rsurface.frameblend[0].lerp = 1;
10840 rsurface.ent_alttextures = false;
10841 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10842 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10845 rsurface.modelvertex3f = vertex3f;
10846 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10847 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10848 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10850 else if (wantnormals)
10852 rsurface.modelvertex3f = vertex3f;
10853 rsurface.modelsvector3f = NULL;
10854 rsurface.modeltvector3f = NULL;
10855 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10859 rsurface.modelvertex3f = vertex3f;
10860 rsurface.modelsvector3f = NULL;
10861 rsurface.modeltvector3f = NULL;
10862 rsurface.modelnormal3f = NULL;
10864 rsurface.modelvertexmesh = NULL;
10865 rsurface.modelvertexmeshbuffer = NULL;
10866 rsurface.modelvertexposition = NULL;
10867 rsurface.modelvertexpositionbuffer = NULL;
10868 rsurface.modelvertex3f_vertexbuffer = 0;
10869 rsurface.modelvertex3f_bufferoffset = 0;
10870 rsurface.modelsvector3f_vertexbuffer = 0;
10871 rsurface.modelsvector3f_bufferoffset = 0;
10872 rsurface.modeltvector3f_vertexbuffer = 0;
10873 rsurface.modeltvector3f_bufferoffset = 0;
10874 rsurface.modelnormal3f_vertexbuffer = 0;
10875 rsurface.modelnormal3f_bufferoffset = 0;
10876 rsurface.modelgeneratedvertex = true;
10877 rsurface.modellightmapcolor4f = color4f;
10878 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10879 rsurface.modellightmapcolor4f_bufferoffset = 0;
10880 rsurface.modeltexcoordtexture2f = texcoord2f;
10881 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10882 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10883 rsurface.modeltexcoordlightmap2f = NULL;
10884 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10885 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10886 rsurface.modelelement3i = element3i;
10887 rsurface.modelelement3i_indexbuffer = NULL;
10888 rsurface.modelelement3i_bufferoffset = 0;
10889 rsurface.modelelement3s = element3s;
10890 rsurface.modelelement3s_indexbuffer = NULL;
10891 rsurface.modelelement3s_bufferoffset = 0;
10892 rsurface.modellightmapoffsets = NULL;
10893 rsurface.modelsurfaces = NULL;
10894 rsurface.batchgeneratedvertex = false;
10895 rsurface.batchfirstvertex = 0;
10896 rsurface.batchnumvertices = 0;
10897 rsurface.batchfirsttriangle = 0;
10898 rsurface.batchnumtriangles = 0;
10899 rsurface.batchvertex3f = NULL;
10900 rsurface.batchvertex3f_vertexbuffer = NULL;
10901 rsurface.batchvertex3f_bufferoffset = 0;
10902 rsurface.batchsvector3f = NULL;
10903 rsurface.batchsvector3f_vertexbuffer = NULL;
10904 rsurface.batchsvector3f_bufferoffset = 0;
10905 rsurface.batchtvector3f = NULL;
10906 rsurface.batchtvector3f_vertexbuffer = NULL;
10907 rsurface.batchtvector3f_bufferoffset = 0;
10908 rsurface.batchnormal3f = NULL;
10909 rsurface.batchnormal3f_vertexbuffer = NULL;
10910 rsurface.batchnormal3f_bufferoffset = 0;
10911 rsurface.batchlightmapcolor4f = NULL;
10912 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10913 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10914 rsurface.batchtexcoordtexture2f = NULL;
10915 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10916 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10917 rsurface.batchtexcoordlightmap2f = NULL;
10918 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10919 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10920 rsurface.batchvertexmesh = NULL;
10921 rsurface.batchvertexmeshbuffer = NULL;
10922 rsurface.batchvertexposition = NULL;
10923 rsurface.batchvertexpositionbuffer = NULL;
10924 rsurface.batchelement3i = NULL;
10925 rsurface.batchelement3i_indexbuffer = NULL;
10926 rsurface.batchelement3i_bufferoffset = 0;
10927 rsurface.batchelement3s = NULL;
10928 rsurface.batchelement3s_indexbuffer = NULL;
10929 rsurface.batchelement3s_bufferoffset = 0;
10930 rsurface.passcolor4f = NULL;
10931 rsurface.passcolor4f_vertexbuffer = NULL;
10932 rsurface.passcolor4f_bufferoffset = 0;
10934 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10936 if ((wantnormals || wanttangents) && !normal3f)
10938 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10939 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10941 if (wanttangents && !svector3f)
10943 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10944 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10945 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10949 // now convert arrays into vertexmesh structs
10950 for (i = 0;i < numvertices;i++)
10952 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10953 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10954 if (rsurface.modelsvector3f)
10955 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10956 if (rsurface.modeltvector3f)
10957 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10958 if (rsurface.modelnormal3f)
10959 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10960 if (rsurface.modellightmapcolor4f)
10961 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10962 if (rsurface.modeltexcoordtexture2f)
10963 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10964 if (rsurface.modeltexcoordlightmap2f)
10965 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10969 float RSurf_FogPoint(const float *v)
10971 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10972 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10973 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10974 float FogHeightFade = r_refdef.fogheightfade;
10976 unsigned int fogmasktableindex;
10977 if (r_refdef.fogplaneviewabove)
10978 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10980 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10981 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10982 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10985 float RSurf_FogVertex(const float *v)
10987 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10988 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10989 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10990 float FogHeightFade = rsurface.fogheightfade;
10992 unsigned int fogmasktableindex;
10993 if (r_refdef.fogplaneviewabove)
10994 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10996 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10997 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10998 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11001 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11004 for (i = 0;i < numelements;i++)
11005 outelement3i[i] = inelement3i[i] + adjust;
11008 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11009 extern cvar_t gl_vbo;
11010 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11018 int surfacefirsttriangle;
11019 int surfacenumtriangles;
11020 int surfacefirstvertex;
11021 int surfaceendvertex;
11022 int surfacenumvertices;
11023 int surfaceadjustvertex;
11027 qboolean dynamicvertex;
11031 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11032 float waveparms[4];
11033 q3shaderinfo_deform_t *deform;
11034 const msurface_t *surface, *firstsurface;
11035 r_vertexposition_t *vertexposition;
11036 r_vertexmesh_t *vertexmesh;
11037 if (!texturenumsurfaces)
11039 // find vertex range of this surface batch
11041 firstsurface = texturesurfacelist[0];
11042 firsttriangle = firstsurface->num_firsttriangle;
11044 firstvertex = endvertex = firstsurface->num_firstvertex;
11045 for (i = 0;i < texturenumsurfaces;i++)
11047 surface = texturesurfacelist[i];
11048 if (surface != firstsurface + i)
11050 surfacefirstvertex = surface->num_firstvertex;
11051 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11052 surfacenumtriangles = surface->num_triangles;
11053 if (firstvertex > surfacefirstvertex)
11054 firstvertex = surfacefirstvertex;
11055 if (endvertex < surfaceendvertex)
11056 endvertex = surfaceendvertex;
11057 numtriangles += surfacenumtriangles;
11062 // we now know the vertex range used, and if there are any gaps in it
11063 rsurface.batchfirstvertex = firstvertex;
11064 rsurface.batchnumvertices = endvertex - firstvertex;
11065 rsurface.batchfirsttriangle = firsttriangle;
11066 rsurface.batchnumtriangles = numtriangles;
11068 // this variable holds flags for which properties have been updated that
11069 // may require regenerating vertexmesh or vertexposition arrays...
11072 // check if any dynamic vertex processing must occur
11073 dynamicvertex = false;
11075 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11076 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11077 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11079 switch (deform->deform)
11082 case Q3DEFORM_PROJECTIONSHADOW:
11083 case Q3DEFORM_TEXT0:
11084 case Q3DEFORM_TEXT1:
11085 case Q3DEFORM_TEXT2:
11086 case Q3DEFORM_TEXT3:
11087 case Q3DEFORM_TEXT4:
11088 case Q3DEFORM_TEXT5:
11089 case Q3DEFORM_TEXT6:
11090 case Q3DEFORM_TEXT7:
11091 case Q3DEFORM_NONE:
11093 case Q3DEFORM_AUTOSPRITE:
11094 dynamicvertex = true;
11095 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11096 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11098 case Q3DEFORM_AUTOSPRITE2:
11099 dynamicvertex = true;
11100 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11101 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11103 case Q3DEFORM_NORMAL:
11104 dynamicvertex = true;
11105 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11106 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11108 case Q3DEFORM_WAVE:
11109 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11110 break; // if wavefunc is a nop, ignore this transform
11111 dynamicvertex = true;
11112 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11113 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11115 case Q3DEFORM_BULGE:
11116 dynamicvertex = true;
11117 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11118 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11120 case Q3DEFORM_MOVE:
11121 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11122 break; // if wavefunc is a nop, ignore this transform
11123 dynamicvertex = true;
11124 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11125 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11129 switch(rsurface.texture->tcgen.tcgen)
11132 case Q3TCGEN_TEXTURE:
11134 case Q3TCGEN_LIGHTMAP:
11135 dynamicvertex = true;
11136 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11137 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11139 case Q3TCGEN_VECTOR:
11140 dynamicvertex = true;
11141 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11142 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11144 case Q3TCGEN_ENVIRONMENT:
11145 dynamicvertex = true;
11146 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11147 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11150 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11152 dynamicvertex = true;
11153 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11154 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11157 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11159 dynamicvertex = true;
11160 batchneed |= BATCHNEED_NOGAPS;
11161 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11164 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11166 dynamicvertex = true;
11167 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11168 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11171 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11173 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11174 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11175 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11176 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11177 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11178 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11179 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11182 // when the model data has no vertex buffer (dynamic mesh), we need to
11184 if (!rsurface.modelvertexmeshbuffer)
11185 batchneed |= BATCHNEED_NOGAPS;
11187 // if needsupdate, we have to do a dynamic vertex batch for sure
11188 if (needsupdate & batchneed)
11189 dynamicvertex = true;
11191 // see if we need to build vertexmesh from arrays
11192 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11193 dynamicvertex = true;
11195 // see if we need to build vertexposition from arrays
11196 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11197 dynamicvertex = true;
11199 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11200 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11201 dynamicvertex = true;
11203 // if there is a chance of animated vertex colors, it's a dynamic batch
11204 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11205 dynamicvertex = true;
11207 rsurface.batchvertex3f = rsurface.modelvertex3f;
11208 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11209 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11210 rsurface.batchsvector3f = rsurface.modelsvector3f;
11211 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11212 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11213 rsurface.batchtvector3f = rsurface.modeltvector3f;
11214 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11215 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11216 rsurface.batchnormal3f = rsurface.modelnormal3f;
11217 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11218 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11219 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11220 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11221 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11222 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11223 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11224 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11225 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11226 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11227 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11228 rsurface.batchvertexposition = rsurface.modelvertexposition;
11229 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11230 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11231 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11232 rsurface.batchelement3i = rsurface.modelelement3i;
11233 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11234 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11235 rsurface.batchelement3s = rsurface.modelelement3s;
11236 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11237 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11239 // if any dynamic vertex processing has to occur in software, we copy the
11240 // entire surface list together before processing to rebase the vertices
11241 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11243 // if any gaps exist and we do not have a static vertex buffer, we have to
11244 // copy the surface list together to avoid wasting upload bandwidth on the
11245 // vertices in the gaps.
11247 // if gaps exist and we have a static vertex buffer, we still have to
11248 // combine the index buffer ranges into one dynamic index buffer.
11250 // in all cases we end up with data that can be drawn in one call.
11252 if (!dynamicvertex)
11254 // static vertex data, just set pointers...
11255 rsurface.batchgeneratedvertex = false;
11256 // if there are gaps, we want to build a combined index buffer,
11257 // otherwise use the original static buffer with an appropriate offset
11262 for (i = 0;i < texturenumsurfaces;i++)
11264 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11265 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11266 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11267 numtriangles += surfacenumtriangles;
11269 rsurface.batchelement3i = rsurface.array_batchelement3i;
11270 rsurface.batchelement3i_indexbuffer = NULL;
11271 rsurface.batchelement3i_bufferoffset = 0;
11272 rsurface.batchelement3s = NULL;
11273 rsurface.batchelement3s_indexbuffer = NULL;
11274 rsurface.batchelement3s_bufferoffset = 0;
11275 if (endvertex <= 65536)
11277 rsurface.batchelement3s = rsurface.array_batchelement3s;
11278 for (i = 0;i < numtriangles*3;i++)
11279 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11281 rsurface.batchfirsttriangle = firsttriangle;
11282 rsurface.batchnumtriangles = numtriangles;
11287 // something needs software processing, do it for real...
11288 // we only directly handle interleaved array data in this case...
11289 rsurface.batchgeneratedvertex = true;
11291 // now copy the vertex data into a combined array and make an index array
11292 // (this is what Quake3 does all the time)
11293 //if (gaps || rsurface.batchfirstvertex)
11295 rsurface.batchvertexposition = NULL;
11296 rsurface.batchvertexpositionbuffer = NULL;
11297 rsurface.batchvertexmesh = NULL;
11298 rsurface.batchvertexmeshbuffer = NULL;
11299 rsurface.batchvertex3f = NULL;
11300 rsurface.batchvertex3f_vertexbuffer = NULL;
11301 rsurface.batchvertex3f_bufferoffset = 0;
11302 rsurface.batchsvector3f = NULL;
11303 rsurface.batchsvector3f_vertexbuffer = NULL;
11304 rsurface.batchsvector3f_bufferoffset = 0;
11305 rsurface.batchtvector3f = NULL;
11306 rsurface.batchtvector3f_vertexbuffer = NULL;
11307 rsurface.batchtvector3f_bufferoffset = 0;
11308 rsurface.batchnormal3f = NULL;
11309 rsurface.batchnormal3f_vertexbuffer = NULL;
11310 rsurface.batchnormal3f_bufferoffset = 0;
11311 rsurface.batchlightmapcolor4f = NULL;
11312 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11313 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11314 rsurface.batchtexcoordtexture2f = NULL;
11315 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11316 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11317 rsurface.batchtexcoordlightmap2f = NULL;
11318 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11319 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11320 rsurface.batchelement3i = rsurface.array_batchelement3i;
11321 rsurface.batchelement3i_indexbuffer = NULL;
11322 rsurface.batchelement3i_bufferoffset = 0;
11323 rsurface.batchelement3s = NULL;
11324 rsurface.batchelement3s_indexbuffer = NULL;
11325 rsurface.batchelement3s_bufferoffset = 0;
11326 // we'll only be setting up certain arrays as needed
11327 if (batchneed & BATCHNEED_VERTEXPOSITION)
11328 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11329 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11330 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11331 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11332 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11333 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11334 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11335 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11337 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11338 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11340 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11341 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11342 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11343 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11344 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11345 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11348 for (i = 0;i < texturenumsurfaces;i++)
11350 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11351 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11352 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11353 surfaceadjustvertex = numvertices - surfacefirstvertex;
11354 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11355 // copy only the data requested
11356 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11357 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11358 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11359 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11360 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11362 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11363 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11364 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11365 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11366 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11368 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11369 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11371 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11372 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11373 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11374 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11375 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11376 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11378 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11379 numvertices += surfacenumvertices;
11380 numtriangles += surfacenumtriangles;
11383 // generate a 16bit index array as well if possible
11384 // (in general, dynamic batches fit)
11385 if (numvertices <= 65536)
11387 rsurface.batchelement3s = rsurface.array_batchelement3s;
11388 for (i = 0;i < numtriangles*3;i++)
11389 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11392 // since we've copied everything, the batch now starts at 0
11393 rsurface.batchfirstvertex = 0;
11394 rsurface.batchnumvertices = numvertices;
11395 rsurface.batchfirsttriangle = 0;
11396 rsurface.batchnumtriangles = numtriangles;
11399 // q1bsp surfaces rendered in vertex color mode have to have colors
11400 // calculated based on lightstyles
11401 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11403 // generate color arrays for the surfaces in this list
11407 const int *offsets;
11408 const unsigned char *lm;
11410 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11411 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11412 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11413 for (i = 0;i < texturenumsurfaces;i++)
11415 surface = texturesurfacelist[i];
11416 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11417 surfacenumvertices = surface->num_vertices;
11418 if (surface->lightmapinfo->samples)
11420 for (j = 0;j < surfacenumvertices;j++)
11422 lm = surface->lightmapinfo->samples + offsets[j];
11423 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11424 VectorScale(lm, scale, c);
11425 if (surface->lightmapinfo->styles[1] != 255)
11427 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11429 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11430 VectorMA(c, scale, lm, c);
11431 if (surface->lightmapinfo->styles[2] != 255)
11434 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11435 VectorMA(c, scale, lm, c);
11436 if (surface->lightmapinfo->styles[3] != 255)
11439 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11440 VectorMA(c, scale, lm, c);
11447 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
11453 for (j = 0;j < surfacenumvertices;j++)
11455 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11462 // if vertices are deformed (sprite flares and things in maps, possibly
11463 // water waves, bulges and other deformations), modify the copied vertices
11465 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11467 switch (deform->deform)
11470 case Q3DEFORM_PROJECTIONSHADOW:
11471 case Q3DEFORM_TEXT0:
11472 case Q3DEFORM_TEXT1:
11473 case Q3DEFORM_TEXT2:
11474 case Q3DEFORM_TEXT3:
11475 case Q3DEFORM_TEXT4:
11476 case Q3DEFORM_TEXT5:
11477 case Q3DEFORM_TEXT6:
11478 case Q3DEFORM_TEXT7:
11479 case Q3DEFORM_NONE:
11481 case Q3DEFORM_AUTOSPRITE:
11482 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11483 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11484 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11485 VectorNormalize(newforward);
11486 VectorNormalize(newright);
11487 VectorNormalize(newup);
11488 // a single autosprite surface can contain multiple sprites...
11489 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11491 VectorClear(center);
11492 for (i = 0;i < 4;i++)
11493 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11494 VectorScale(center, 0.25f, center);
11495 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11496 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11497 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11498 for (i = 0;i < 4;i++)
11500 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11501 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11504 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11505 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11506 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11507 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11508 rsurface.batchvertex3f_vertexbuffer = NULL;
11509 rsurface.batchvertex3f_bufferoffset = 0;
11510 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11511 rsurface.batchsvector3f_vertexbuffer = NULL;
11512 rsurface.batchsvector3f_bufferoffset = 0;
11513 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11514 rsurface.batchtvector3f_vertexbuffer = NULL;
11515 rsurface.batchtvector3f_bufferoffset = 0;
11516 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11517 rsurface.batchnormal3f_vertexbuffer = NULL;
11518 rsurface.batchnormal3f_bufferoffset = 0;
11520 case Q3DEFORM_AUTOSPRITE2:
11521 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11522 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11523 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11524 VectorNormalize(newforward);
11525 VectorNormalize(newright);
11526 VectorNormalize(newup);
11528 const float *v1, *v2;
11538 memset(shortest, 0, sizeof(shortest));
11539 // a single autosprite surface can contain multiple sprites...
11540 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11542 VectorClear(center);
11543 for (i = 0;i < 4;i++)
11544 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11545 VectorScale(center, 0.25f, center);
11546 // find the two shortest edges, then use them to define the
11547 // axis vectors for rotating around the central axis
11548 for (i = 0;i < 6;i++)
11550 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11551 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11552 l = VectorDistance2(v1, v2);
11553 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11554 if (v1[2] != v2[2])
11555 l += (1.0f / 1024.0f);
11556 if (shortest[0].length2 > l || i == 0)
11558 shortest[1] = shortest[0];
11559 shortest[0].length2 = l;
11560 shortest[0].v1 = v1;
11561 shortest[0].v2 = v2;
11563 else if (shortest[1].length2 > l || i == 1)
11565 shortest[1].length2 = l;
11566 shortest[1].v1 = v1;
11567 shortest[1].v2 = v2;
11570 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11571 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11572 // this calculates the right vector from the shortest edge
11573 // and the up vector from the edge midpoints
11574 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11575 VectorNormalize(right);
11576 VectorSubtract(end, start, up);
11577 VectorNormalize(up);
11578 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11579 VectorSubtract(rsurface.localvieworigin, center, forward);
11580 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11581 VectorNegate(forward, forward);
11582 VectorReflect(forward, 0, up, forward);
11583 VectorNormalize(forward);
11584 CrossProduct(up, forward, newright);
11585 VectorNormalize(newright);
11586 // rotate the quad around the up axis vector, this is made
11587 // especially easy by the fact we know the quad is flat,
11588 // so we only have to subtract the center position and
11589 // measure distance along the right vector, and then
11590 // multiply that by the newright vector and add back the
11592 // we also need to subtract the old position to undo the
11593 // displacement from the center, which we do with a
11594 // DotProduct, the subtraction/addition of center is also
11595 // optimized into DotProducts here
11596 l = DotProduct(right, center);
11597 for (i = 0;i < 4;i++)
11599 v1 = rsurface.batchvertex3f + 3*(j+i);
11600 f = DotProduct(right, v1) - l;
11601 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11605 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11606 rsurface.batchvertex3f_vertexbuffer = NULL;
11607 rsurface.batchvertex3f_bufferoffset = 0;
11608 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11610 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11611 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11612 rsurface.batchnormal3f_vertexbuffer = NULL;
11613 rsurface.batchnormal3f_bufferoffset = 0;
11615 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11617 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11618 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11619 rsurface.batchsvector3f_vertexbuffer = NULL;
11620 rsurface.batchsvector3f_bufferoffset = 0;
11621 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11622 rsurface.batchtvector3f_vertexbuffer = NULL;
11623 rsurface.batchtvector3f_bufferoffset = 0;
11626 case Q3DEFORM_NORMAL:
11627 // deform the normals to make reflections wavey
11628 for (j = 0;j < rsurface.batchnumvertices;j++)
11631 float *normal = rsurface.array_batchnormal3f + 3*j;
11632 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11633 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11634 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11635 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11636 VectorNormalize(normal);
11638 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11639 rsurface.batchnormal3f_vertexbuffer = NULL;
11640 rsurface.batchnormal3f_bufferoffset = 0;
11641 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11643 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11644 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11645 rsurface.batchsvector3f_vertexbuffer = NULL;
11646 rsurface.batchsvector3f_bufferoffset = 0;
11647 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11648 rsurface.batchtvector3f_vertexbuffer = NULL;
11649 rsurface.batchtvector3f_bufferoffset = 0;
11652 case Q3DEFORM_WAVE:
11653 // deform vertex array to make wavey water and flags and such
11654 waveparms[0] = deform->waveparms[0];
11655 waveparms[1] = deform->waveparms[1];
11656 waveparms[2] = deform->waveparms[2];
11657 waveparms[3] = deform->waveparms[3];
11658 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11659 break; // if wavefunc is a nop, don't make a dynamic vertex array
11660 // this is how a divisor of vertex influence on deformation
11661 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11662 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11663 for (j = 0;j < rsurface.batchnumvertices;j++)
11665 // if the wavefunc depends on time, evaluate it per-vertex
11668 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11669 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11671 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11673 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11674 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11675 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11676 rsurface.batchvertex3f_vertexbuffer = NULL;
11677 rsurface.batchvertex3f_bufferoffset = 0;
11678 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11679 rsurface.batchnormal3f_vertexbuffer = NULL;
11680 rsurface.batchnormal3f_bufferoffset = 0;
11681 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11683 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11684 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11685 rsurface.batchsvector3f_vertexbuffer = NULL;
11686 rsurface.batchsvector3f_bufferoffset = 0;
11687 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11688 rsurface.batchtvector3f_vertexbuffer = NULL;
11689 rsurface.batchtvector3f_bufferoffset = 0;
11692 case Q3DEFORM_BULGE:
11693 // deform vertex array to make the surface have moving bulges
11694 for (j = 0;j < rsurface.batchnumvertices;j++)
11696 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11697 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11699 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11700 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11701 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11702 rsurface.batchvertex3f_vertexbuffer = NULL;
11703 rsurface.batchvertex3f_bufferoffset = 0;
11704 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11705 rsurface.batchnormal3f_vertexbuffer = NULL;
11706 rsurface.batchnormal3f_bufferoffset = 0;
11707 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11709 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11710 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11711 rsurface.batchsvector3f_vertexbuffer = NULL;
11712 rsurface.batchsvector3f_bufferoffset = 0;
11713 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11714 rsurface.batchtvector3f_vertexbuffer = NULL;
11715 rsurface.batchtvector3f_bufferoffset = 0;
11718 case Q3DEFORM_MOVE:
11719 // deform vertex array
11720 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11721 break; // if wavefunc is a nop, don't make a dynamic vertex array
11722 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11723 VectorScale(deform->parms, scale, waveparms);
11724 for (j = 0;j < rsurface.batchnumvertices;j++)
11725 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11726 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11727 rsurface.batchvertex3f_vertexbuffer = NULL;
11728 rsurface.batchvertex3f_bufferoffset = 0;
11733 // generate texcoords based on the chosen texcoord source
11734 switch(rsurface.texture->tcgen.tcgen)
11737 case Q3TCGEN_TEXTURE:
11739 case Q3TCGEN_LIGHTMAP:
11740 if (rsurface.batchtexcoordlightmap2f)
11741 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11742 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11743 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11744 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11746 case Q3TCGEN_VECTOR:
11747 for (j = 0;j < rsurface.batchnumvertices;j++)
11749 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11750 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11752 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11753 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11754 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11756 case Q3TCGEN_ENVIRONMENT:
11757 // make environment reflections using a spheremap
11758 for (j = 0;j < rsurface.batchnumvertices;j++)
11760 // identical to Q3A's method, but executed in worldspace so
11761 // carried models can be shiny too
11763 float viewer[3], d, reflected[3], worldreflected[3];
11765 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11766 // VectorNormalize(viewer);
11768 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11770 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11771 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11772 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11773 // note: this is proportinal to viewer, so we can normalize later
11775 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11776 VectorNormalize(worldreflected);
11778 // note: this sphere map only uses world x and z!
11779 // so positive and negative y will LOOK THE SAME.
11780 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11781 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11783 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11784 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11785 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11788 // the only tcmod that needs software vertex processing is turbulent, so
11789 // check for it here and apply the changes if needed
11790 // and we only support that as the first one
11791 // (handling a mixture of turbulent and other tcmods would be problematic
11792 // without punting it entirely to a software path)
11793 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11795 amplitude = rsurface.texture->tcmods[0].parms[1];
11796 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11797 for (j = 0;j < rsurface.batchnumvertices;j++)
11799 rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11800 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11802 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11803 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11804 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11807 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11809 // convert the modified arrays to vertex structs
11810 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11811 rsurface.batchvertexmeshbuffer = NULL;
11812 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11813 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11814 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11815 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11816 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11817 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11818 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11820 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11822 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11823 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11826 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11827 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11828 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11829 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11830 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11831 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11832 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11833 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11834 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11837 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11839 // convert the modified arrays to vertex structs
11840 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11841 rsurface.batchvertexpositionbuffer = NULL;
11842 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11843 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11845 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11846 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11850 void RSurf_DrawBatch(void)
11852 R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
11855 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11857 // pick the closest matching water plane
11858 int planeindex, vertexindex, bestplaneindex = -1;
11862 r_waterstate_waterplane_t *p;
11864 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11866 if(p->camera_entity != rsurface.texture->camera_entity)
11869 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11870 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11872 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11873 d += fabs(PlaneDiff(vert, &p->plane));
11875 if (bestd > d || bestplaneindex < 0)
11878 bestplaneindex = planeindex;
11881 return bestplaneindex;
11884 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11887 for (i = 0;i < rsurface.batchnumvertices;i++)
11888 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11889 rsurface.passcolor4f = rsurface.array_passcolor4f;
11890 rsurface.passcolor4f_vertexbuffer = 0;
11891 rsurface.passcolor4f_bufferoffset = 0;
11894 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11901 if (rsurface.passcolor4f)
11903 // generate color arrays
11904 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
11906 f = RSurf_FogVertex(v);
11915 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11917 f = RSurf_FogVertex(v);
11924 rsurface.passcolor4f = rsurface.array_passcolor4f;
11925 rsurface.passcolor4f_vertexbuffer = 0;
11926 rsurface.passcolor4f_bufferoffset = 0;
11929 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11936 if (!rsurface.passcolor4f)
11938 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
11940 f = RSurf_FogVertex(v);
11941 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11942 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11943 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11946 rsurface.passcolor4f = rsurface.array_passcolor4f;
11947 rsurface.passcolor4f_vertexbuffer = 0;
11948 rsurface.passcolor4f_bufferoffset = 0;
11951 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11956 if (!rsurface.passcolor4f)
11958 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11965 rsurface.passcolor4f = rsurface.array_passcolor4f;
11966 rsurface.passcolor4f_vertexbuffer = 0;
11967 rsurface.passcolor4f_bufferoffset = 0;
11970 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11975 if (!rsurface.passcolor4f)
11977 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11979 c2[0] = c[0] + r_refdef.scene.ambient;
11980 c2[1] = c[1] + r_refdef.scene.ambient;
11981 c2[2] = c[2] + r_refdef.scene.ambient;
11984 rsurface.passcolor4f = rsurface.array_passcolor4f;
11985 rsurface.passcolor4f_vertexbuffer = 0;
11986 rsurface.passcolor4f_bufferoffset = 0;
11989 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11992 rsurface.passcolor4f = NULL;
11993 rsurface.passcolor4f_vertexbuffer = 0;
11994 rsurface.passcolor4f_bufferoffset = 0;
11995 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11996 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11997 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11998 GL_Color(r, g, b, a);
11999 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12003 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12005 // TODO: optimize applyfog && applycolor case
12006 // just apply fog if necessary, and tint the fog color array if necessary
12007 rsurface.passcolor4f = NULL;
12008 rsurface.passcolor4f_vertexbuffer = 0;
12009 rsurface.passcolor4f_bufferoffset = 0;
12010 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12011 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12012 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12013 GL_Color(r, g, b, a);
12017 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12020 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12021 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12022 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12023 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12024 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12025 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12026 GL_Color(r, g, b, a);
12030 static void RSurf_DrawBatch_GL11_ClampColor(void)
12035 if (!rsurface.passcolor4f)
12037 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12039 c2[0] = bound(0.0f, c1[0], 1.0f);
12040 c2[1] = bound(0.0f, c1[1], 1.0f);
12041 c2[2] = bound(0.0f, c1[2], 1.0f);
12042 c2[3] = bound(0.0f, c1[3], 1.0f);
12046 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12054 vec3_t ambientcolor;
12055 vec3_t diffusecolor;
12059 VectorCopy(rsurface.modellight_lightdir, lightdir);
12060 f = 0.5f * r_refdef.lightmapintensity;
12061 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12062 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12063 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12064 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12065 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12066 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12068 if (VectorLength2(diffusecolor) > 0)
12070 // q3-style directional shading
12071 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12073 if ((f = DotProduct(n, lightdir)) > 0)
12074 VectorMA(ambientcolor, f, diffusecolor, c);
12076 VectorCopy(ambientcolor, c);
12083 rsurface.passcolor4f = rsurface.array_passcolor4f;
12084 rsurface.passcolor4f_vertexbuffer = 0;
12085 rsurface.passcolor4f_bufferoffset = 0;
12086 *applycolor = false;
12090 *r = ambientcolor[0];
12091 *g = ambientcolor[1];
12092 *b = ambientcolor[2];
12093 rsurface.passcolor4f = NULL;
12094 rsurface.passcolor4f_vertexbuffer = 0;
12095 rsurface.passcolor4f_bufferoffset = 0;
12099 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12101 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12102 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12103 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12104 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12105 GL_Color(r, g, b, a);
12109 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12115 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12117 f = 1 - RSurf_FogVertex(v);
12125 void RSurf_SetupDepthAndCulling(void)
12127 // submodels are biased to avoid z-fighting with world surfaces that they
12128 // may be exactly overlapping (avoids z-fighting artifacts on certain
12129 // doors and things in Quake maps)
12130 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12131 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12132 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12133 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12136 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12138 // transparent sky would be ridiculous
12139 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12141 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12142 skyrenderlater = true;
12143 RSurf_SetupDepthAndCulling();
12144 GL_DepthMask(true);
12145 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12146 // skymasking on them, and Quake3 never did sky masking (unlike
12147 // software Quake and software Quake2), so disable the sky masking
12148 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12149 // and skymasking also looks very bad when noclipping outside the
12150 // level, so don't use it then either.
12151 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12153 R_Mesh_ResetTextureState();
12154 if (skyrendermasked)
12156 R_SetupShader_DepthOrShadow();
12157 // depth-only (masking)
12158 GL_ColorMask(0,0,0,0);
12159 // just to make sure that braindead drivers don't draw
12160 // anything despite that colormask...
12161 GL_BlendFunc(GL_ZERO, GL_ONE);
12162 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12163 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12169 GL_BlendFunc(GL_ONE, GL_ZERO);
12170 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12171 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12172 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12175 if (skyrendermasked)
12176 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12178 R_Mesh_ResetTextureState();
12179 GL_Color(1, 1, 1, 1);
12182 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12183 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12184 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12186 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12190 // render screenspace normalmap to texture
12191 GL_DepthMask(true);
12192 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12197 // bind lightmap texture
12199 // water/refraction/reflection/camera surfaces have to be handled specially
12200 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12202 int start, end, startplaneindex;
12203 for (start = 0;start < texturenumsurfaces;start = end)
12205 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12206 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12208 // now that we have a batch using the same planeindex, render it
12209 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12211 // render water or distortion background
12212 GL_DepthMask(true);
12213 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12215 // blend surface on top
12216 GL_DepthMask(false);
12217 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12220 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12222 // render surface with reflection texture as input
12223 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12224 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12231 // render surface batch normally
12232 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12233 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12237 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12239 // OpenGL 1.3 path - anything not completely ancient
12240 qboolean applycolor;
12243 const texturelayer_t *layer;
12244 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12245 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12247 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12250 int layertexrgbscale;
12251 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12253 if (layerindex == 0)
12254 GL_AlphaTest(true);
12257 GL_AlphaTest(false);
12258 GL_DepthFunc(GL_EQUAL);
12261 GL_DepthMask(layer->depthmask && writedepth);
12262 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12263 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12265 layertexrgbscale = 4;
12266 VectorScale(layer->color, 0.25f, layercolor);
12268 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12270 layertexrgbscale = 2;
12271 VectorScale(layer->color, 0.5f, layercolor);
12275 layertexrgbscale = 1;
12276 VectorScale(layer->color, 1.0f, layercolor);
12278 layercolor[3] = layer->color[3];
12279 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12280 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12281 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12282 switch (layer->type)
12284 case TEXTURELAYERTYPE_LITTEXTURE:
12285 // single-pass lightmapped texture with 2x rgbscale
12286 R_Mesh_TexBind(0, r_texture_white);
12287 R_Mesh_TexMatrix(0, NULL);
12288 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12289 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12290 R_Mesh_TexBind(1, layer->texture);
12291 R_Mesh_TexMatrix(1, &layer->texmatrix);
12292 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12293 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12294 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12295 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12296 else if (rsurface.uselightmaptexture)
12297 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12299 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12301 case TEXTURELAYERTYPE_TEXTURE:
12302 // singletexture unlit texture with transparency support
12303 R_Mesh_TexBind(0, layer->texture);
12304 R_Mesh_TexMatrix(0, &layer->texmatrix);
12305 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12306 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12307 R_Mesh_TexBind(1, 0);
12308 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12309 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12311 case TEXTURELAYERTYPE_FOG:
12312 // singletexture fogging
12313 if (layer->texture)
12315 R_Mesh_TexBind(0, layer->texture);
12316 R_Mesh_TexMatrix(0, &layer->texmatrix);
12317 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12318 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12322 R_Mesh_TexBind(0, 0);
12323 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12325 R_Mesh_TexBind(1, 0);
12326 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12327 // generate a color array for the fog pass
12328 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12329 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12333 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12338 GL_DepthFunc(GL_LEQUAL);
12339 GL_AlphaTest(false);
12343 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12345 // OpenGL 1.1 - crusty old voodoo path
12348 const texturelayer_t *layer;
12349 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12350 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12352 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12356 if (layerindex == 0)
12357 GL_AlphaTest(true);
12360 GL_AlphaTest(false);
12361 GL_DepthFunc(GL_EQUAL);
12364 GL_DepthMask(layer->depthmask && writedepth);
12365 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12366 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12367 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12368 switch (layer->type)
12370 case TEXTURELAYERTYPE_LITTEXTURE:
12371 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12373 // two-pass lit texture with 2x rgbscale
12374 // first the lightmap pass
12375 R_Mesh_TexBind(0, r_texture_white);
12376 R_Mesh_TexMatrix(0, NULL);
12377 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12378 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12379 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12380 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12381 else if (rsurface.uselightmaptexture)
12382 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12384 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12385 // then apply the texture to it
12386 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12387 R_Mesh_TexBind(0, layer->texture);
12388 R_Mesh_TexMatrix(0, &layer->texmatrix);
12389 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12390 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12391 RSurf_DrawBatch_GL11_Unlit(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);
12395 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12396 R_Mesh_TexBind(0, layer->texture);
12397 R_Mesh_TexMatrix(0, &layer->texmatrix);
12398 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12399 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12400 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12401 RSurf_DrawBatch_GL11_VertexShade(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);
12403 RSurf_DrawBatch_GL11_VertexColor(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);
12406 case TEXTURELAYERTYPE_TEXTURE:
12407 // singletexture unlit texture with transparency support
12408 R_Mesh_TexBind(0, layer->texture);
12409 R_Mesh_TexMatrix(0, &layer->texmatrix);
12410 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12411 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12412 RSurf_DrawBatch_GL11_Unlit(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);
12414 case TEXTURELAYERTYPE_FOG:
12415 // singletexture fogging
12416 if (layer->texture)
12418 R_Mesh_TexBind(0, layer->texture);
12419 R_Mesh_TexMatrix(0, &layer->texmatrix);
12420 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12421 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12425 R_Mesh_TexBind(0, 0);
12426 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12428 // generate a color array for the fog pass
12429 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12430 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12434 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12439 GL_DepthFunc(GL_LEQUAL);
12440 GL_AlphaTest(false);
12444 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12448 r_vertexgeneric_t *batchvertex;
12451 GL_AlphaTest(false);
12452 R_Mesh_ResetTextureState();
12453 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12455 if(rsurface.texture && rsurface.texture->currentskinframe)
12457 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12458 c[3] *= rsurface.texture->currentalpha;
12468 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12470 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12471 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12472 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12475 // brighten it up (as texture value 127 means "unlit")
12476 c[0] *= 2 * r_refdef.view.colorscale;
12477 c[1] *= 2 * r_refdef.view.colorscale;
12478 c[2] *= 2 * r_refdef.view.colorscale;
12480 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12481 c[3] *= r_wateralpha.value;
12483 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12485 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12486 GL_DepthMask(false);
12488 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12490 GL_BlendFunc(GL_ONE, GL_ONE);
12491 GL_DepthMask(false);
12493 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12495 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12496 GL_DepthMask(false);
12498 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12500 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12501 GL_DepthMask(false);
12505 GL_BlendFunc(GL_ONE, GL_ZERO);
12506 GL_DepthMask(writedepth);
12509 if (r_showsurfaces.integer == 3)
12511 rsurface.passcolor4f = NULL;
12513 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12515 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12517 rsurface.passcolor4f = NULL;
12518 rsurface.passcolor4f_vertexbuffer = 0;
12519 rsurface.passcolor4f_bufferoffset = 0;
12521 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12523 qboolean applycolor = true;
12526 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12528 r_refdef.lightmapintensity = 1;
12529 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12530 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12534 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12536 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12537 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12538 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12541 if(!rsurface.passcolor4f)
12542 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12544 RSurf_DrawBatch_GL11_ApplyAmbient();
12545 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12546 if(r_refdef.fogenabled)
12547 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12548 RSurf_DrawBatch_GL11_ClampColor();
12550 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12551 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12554 else if (!r_refdef.view.showdebug)
12556 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12557 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12558 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12560 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12561 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12563 R_Mesh_PrepareVertices_Generic_Unlock();
12566 else if (r_showsurfaces.integer == 4)
12568 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12569 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12570 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12572 unsigned char c = vi << 3;
12573 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12574 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12576 R_Mesh_PrepareVertices_Generic_Unlock();
12579 else if (r_showsurfaces.integer == 2)
12582 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12583 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12584 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12586 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12587 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12588 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12589 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12590 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12591 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12592 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12594 R_Mesh_PrepareVertices_Generic_Unlock();
12595 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12599 int texturesurfaceindex;
12601 const msurface_t *surface;
12602 unsigned char surfacecolor4ub[4];
12603 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12604 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12606 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12608 surface = texturesurfacelist[texturesurfaceindex];
12609 k = (int)(((size_t)surface) / sizeof(msurface_t));
12610 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12611 for (j = 0;j < surface->num_vertices;j++)
12613 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12614 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12618 R_Mesh_PrepareVertices_Generic_Unlock();
12623 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12626 RSurf_SetupDepthAndCulling();
12627 if (r_showsurfaces.integer)
12629 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12632 switch (vid.renderpath)
12634 case RENDERPATH_GL20:
12635 case RENDERPATH_CGGL:
12636 case RENDERPATH_D3D9:
12637 case RENDERPATH_D3D10:
12638 case RENDERPATH_D3D11:
12639 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12641 case RENDERPATH_GL13:
12642 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12644 case RENDERPATH_GL11:
12645 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12651 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12654 RSurf_SetupDepthAndCulling();
12655 if (r_showsurfaces.integer)
12657 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12660 switch (vid.renderpath)
12662 case RENDERPATH_GL20:
12663 case RENDERPATH_CGGL:
12664 case RENDERPATH_D3D9:
12665 case RENDERPATH_D3D10:
12666 case RENDERPATH_D3D11:
12667 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12669 case RENDERPATH_GL13:
12670 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12672 case RENDERPATH_GL11:
12673 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12679 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12682 int texturenumsurfaces, endsurface;
12683 texture_t *texture;
12684 const msurface_t *surface;
12685 #define MAXBATCH_TRANSPARENTSURFACES 256
12686 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12688 // if the model is static it doesn't matter what value we give for
12689 // wantnormals and wanttangents, so this logic uses only rules applicable
12690 // to a model, knowing that they are meaningless otherwise
12691 if (ent == r_refdef.scene.worldentity)
12692 RSurf_ActiveWorldEntity();
12693 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12694 RSurf_ActiveModelEntity(ent, false, false, false);
12697 switch (vid.renderpath)
12699 case RENDERPATH_GL20:
12700 case RENDERPATH_CGGL:
12701 case RENDERPATH_D3D9:
12702 case RENDERPATH_D3D10:
12703 case RENDERPATH_D3D11:
12704 RSurf_ActiveModelEntity(ent, true, true, false);
12706 case RENDERPATH_GL13:
12707 case RENDERPATH_GL11:
12708 RSurf_ActiveModelEntity(ent, true, false, false);
12713 if (r_transparentdepthmasking.integer)
12715 qboolean setup = false;
12716 for (i = 0;i < numsurfaces;i = j)
12719 surface = rsurface.modelsurfaces + surfacelist[i];
12720 texture = surface->texture;
12721 rsurface.texture = R_GetCurrentTexture(texture);
12722 rsurface.lightmaptexture = NULL;
12723 rsurface.deluxemaptexture = NULL;
12724 rsurface.uselightmaptexture = false;
12725 // scan ahead until we find a different texture
12726 endsurface = min(i + 1024, numsurfaces);
12727 texturenumsurfaces = 0;
12728 texturesurfacelist[texturenumsurfaces++] = surface;
12729 for (;j < endsurface;j++)
12731 surface = rsurface.modelsurfaces + surfacelist[j];
12732 if (texture != surface->texture)
12734 texturesurfacelist[texturenumsurfaces++] = surface;
12736 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12738 // render the range of surfaces as depth
12742 GL_ColorMask(0,0,0,0);
12744 GL_DepthTest(true);
12745 GL_BlendFunc(GL_ONE, GL_ZERO);
12746 GL_DepthMask(true);
12747 GL_AlphaTest(false);
12748 R_Mesh_ResetTextureState();
12749 R_SetupShader_DepthOrShadow();
12751 RSurf_SetupDepthAndCulling();
12752 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12753 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12757 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12760 for (i = 0;i < numsurfaces;i = j)
12763 surface = rsurface.modelsurfaces + surfacelist[i];
12764 texture = surface->texture;
12765 rsurface.texture = R_GetCurrentTexture(texture);
12766 rsurface.lightmaptexture = surface->lightmaptexture;
12767 rsurface.deluxemaptexture = surface->deluxemaptexture;
12768 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12769 // scan ahead until we find a different texture
12770 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12771 texturenumsurfaces = 0;
12772 texturesurfacelist[texturenumsurfaces++] = surface;
12773 for (;j < endsurface;j++)
12775 surface = rsurface.modelsurfaces + surfacelist[j];
12776 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12778 texturesurfacelist[texturenumsurfaces++] = surface;
12780 // render the range of surfaces
12781 if (ent == r_refdef.scene.worldentity)
12782 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12784 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12786 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12787 GL_AlphaTest(false);
12790 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12792 // transparent surfaces get pushed off into the transparent queue
12793 int surfacelistindex;
12794 const msurface_t *surface;
12795 vec3_t tempcenter, center;
12796 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12798 surface = texturesurfacelist[surfacelistindex];
12799 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12800 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12801 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12802 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12803 if (queueentity->transparent_offset) // transparent offset
12805 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12806 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12807 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12809 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12813 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12815 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12817 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12819 RSurf_SetupDepthAndCulling();
12820 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12821 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12825 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12827 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12830 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12833 if (!rsurface.texture->currentnumlayers)
12835 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12836 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12838 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12840 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12841 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12842 else if (!rsurface.texture->currentnumlayers)
12844 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12846 // in the deferred case, transparent surfaces were queued during prepass
12847 if (!r_shadow_usingdeferredprepass)
12848 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12852 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12853 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12858 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12861 texture_t *texture;
12862 // break the surface list down into batches by texture and use of lightmapping
12863 for (i = 0;i < numsurfaces;i = j)
12866 // texture is the base texture pointer, rsurface.texture is the
12867 // current frame/skin the texture is directing us to use (for example
12868 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12869 // use skin 1 instead)
12870 texture = surfacelist[i]->texture;
12871 rsurface.texture = R_GetCurrentTexture(texture);
12872 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12873 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12874 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12875 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12877 // if this texture is not the kind we want, skip ahead to the next one
12878 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12882 // simply scan ahead until we find a different texture or lightmap state
12883 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12885 // render the range of surfaces
12886 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12890 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12894 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12897 if (!rsurface.texture->currentnumlayers)
12899 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12900 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12902 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12904 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12905 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12906 else if (!rsurface.texture->currentnumlayers)
12908 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12910 // in the deferred case, transparent surfaces were queued during prepass
12911 if (!r_shadow_usingdeferredprepass)
12912 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12916 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12917 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12922 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12925 texture_t *texture;
12926 // break the surface list down into batches by texture and use of lightmapping
12927 for (i = 0;i < numsurfaces;i = j)
12930 // texture is the base texture pointer, rsurface.texture is the
12931 // current frame/skin the texture is directing us to use (for example
12932 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12933 // use skin 1 instead)
12934 texture = surfacelist[i]->texture;
12935 rsurface.texture = R_GetCurrentTexture(texture);
12936 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12937 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12938 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12939 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12941 // if this texture is not the kind we want, skip ahead to the next one
12942 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12946 // simply scan ahead until we find a different texture or lightmap state
12947 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12949 // render the range of surfaces
12950 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12954 float locboxvertex3f[6*4*3] =
12956 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12957 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12958 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12959 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12960 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12961 1,0,0, 0,0,0, 0,1,0, 1,1,0
12964 unsigned short locboxelements[6*2*3] =
12969 12,13,14, 12,14,15,
12970 16,17,18, 16,18,19,
12974 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12977 cl_locnode_t *loc = (cl_locnode_t *)ent;
12979 float vertex3f[6*4*3];
12981 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12982 GL_DepthMask(false);
12983 GL_DepthRange(0, 1);
12984 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12985 GL_DepthTest(true);
12986 GL_CullFace(GL_NONE);
12987 R_EntityMatrix(&identitymatrix);
12989 R_Mesh_ResetTextureState();
12991 i = surfacelist[0];
12992 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12993 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12994 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12995 surfacelist[0] < 0 ? 0.5f : 0.125f);
12997 if (VectorCompare(loc->mins, loc->maxs))
12999 VectorSet(size, 2, 2, 2);
13000 VectorMA(loc->mins, -0.5f, size, mins);
13004 VectorCopy(loc->mins, mins);
13005 VectorSubtract(loc->maxs, loc->mins, size);
13008 for (i = 0;i < 6*4*3;)
13009 for (j = 0;j < 3;j++, i++)
13010 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13012 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13013 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13014 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13017 void R_DrawLocs(void)
13020 cl_locnode_t *loc, *nearestloc;
13022 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13023 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13025 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13026 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13030 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13032 if (decalsystem->decals)
13033 Mem_Free(decalsystem->decals);
13034 memset(decalsystem, 0, sizeof(*decalsystem));
13037 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)
13040 tridecal_t *decals;
13043 // expand or initialize the system
13044 if (decalsystem->maxdecals <= decalsystem->numdecals)
13046 decalsystem_t old = *decalsystem;
13047 qboolean useshortelements;
13048 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13049 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13050 decalsystem->decals = (tridecal_t *)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)));
13051 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13052 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13053 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13054 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13055 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13056 if (decalsystem->numdecals)
13057 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13059 Mem_Free(old.decals);
13060 for (i = 0;i < decalsystem->maxdecals*3;i++)
13061 decalsystem->element3i[i] = i;
13062 if (useshortelements)
13063 for (i = 0;i < decalsystem->maxdecals*3;i++)
13064 decalsystem->element3s[i] = i;
13067 // grab a decal and search for another free slot for the next one
13068 decals = decalsystem->decals;
13069 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13070 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13072 decalsystem->freedecal = i;
13073 if (decalsystem->numdecals <= i)
13074 decalsystem->numdecals = i + 1;
13076 // initialize the decal
13078 decal->triangleindex = triangleindex;
13079 decal->surfaceindex = surfaceindex;
13080 decal->decalsequence = decalsequence;
13081 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13082 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13083 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13084 decal->color4ub[0][3] = 255;
13085 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13086 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13087 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13088 decal->color4ub[1][3] = 255;
13089 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13090 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13091 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13092 decal->color4ub[2][3] = 255;
13093 decal->vertex3f[0][0] = v0[0];
13094 decal->vertex3f[0][1] = v0[1];
13095 decal->vertex3f[0][2] = v0[2];
13096 decal->vertex3f[1][0] = v1[0];
13097 decal->vertex3f[1][1] = v1[1];
13098 decal->vertex3f[1][2] = v1[2];
13099 decal->vertex3f[2][0] = v2[0];
13100 decal->vertex3f[2][1] = v2[1];
13101 decal->vertex3f[2][2] = v2[2];
13102 decal->texcoord2f[0][0] = t0[0];
13103 decal->texcoord2f[0][1] = t0[1];
13104 decal->texcoord2f[1][0] = t1[0];
13105 decal->texcoord2f[1][1] = t1[1];
13106 decal->texcoord2f[2][0] = t2[0];
13107 decal->texcoord2f[2][1] = t2[1];
13110 extern cvar_t cl_decals_bias;
13111 extern cvar_t cl_decals_models;
13112 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13113 // baseparms, parms, temps
13114 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
13119 const float *vertex3f;
13121 float points[2][9][3];
13128 e = rsurface.modelelement3i + 3*triangleindex;
13130 vertex3f = rsurface.modelvertex3f;
13132 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13134 index = 3*e[cornerindex];
13135 VectorCopy(vertex3f + index, v[cornerindex]);
13138 //TriangleNormal(v[0], v[1], v[2], normal);
13139 //if (DotProduct(normal, localnormal) < 0.0f)
13141 // clip by each of the box planes formed from the projection matrix
13142 // if anything survives, we emit the decal
13143 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]);
13146 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]);
13149 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]);
13152 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]);
13155 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]);
13158 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]);
13161 // some part of the triangle survived, so we have to accept it...
13164 // dynamic always uses the original triangle
13166 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13168 index = 3*e[cornerindex];
13169 VectorCopy(vertex3f + index, v[cornerindex]);
13172 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13174 // convert vertex positions to texcoords
13175 Matrix4x4_Transform(projection, v[cornerindex], temp);
13176 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13177 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13178 // calculate distance fade from the projection origin
13179 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13180 f = bound(0.0f, f, 1.0f);
13181 c[cornerindex][0] = r * f;
13182 c[cornerindex][1] = g * f;
13183 c[cornerindex][2] = b * f;
13184 c[cornerindex][3] = 1.0f;
13185 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13188 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
13190 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13191 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);
13193 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)
13195 matrix4x4_t projection;
13196 decalsystem_t *decalsystem;
13199 const msurface_t *surface;
13200 const msurface_t *surfaces;
13201 const int *surfacelist;
13202 const texture_t *texture;
13204 int numsurfacelist;
13205 int surfacelistindex;
13208 float localorigin[3];
13209 float localnormal[3];
13210 float localmins[3];
13211 float localmaxs[3];
13214 float planes[6][4];
13217 int bih_triangles_count;
13218 int bih_triangles[256];
13219 int bih_surfaces[256];
13221 decalsystem = &ent->decalsystem;
13222 model = ent->model;
13223 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13225 R_DecalSystem_Reset(&ent->decalsystem);
13229 if (!model->brush.data_leafs && !cl_decals_models.integer)
13231 if (decalsystem->model)
13232 R_DecalSystem_Reset(decalsystem);
13236 if (decalsystem->model != model)
13237 R_DecalSystem_Reset(decalsystem);
13238 decalsystem->model = model;
13240 RSurf_ActiveModelEntity(ent, false, false, false);
13242 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13243 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13244 VectorNormalize(localnormal);
13245 localsize = worldsize*rsurface.inversematrixscale;
13246 localmins[0] = localorigin[0] - localsize;
13247 localmins[1] = localorigin[1] - localsize;
13248 localmins[2] = localorigin[2] - localsize;
13249 localmaxs[0] = localorigin[0] + localsize;
13250 localmaxs[1] = localorigin[1] + localsize;
13251 localmaxs[2] = localorigin[2] + localsize;
13253 //VectorCopy(localnormal, planes[4]);
13254 //VectorVectors(planes[4], planes[2], planes[0]);
13255 AnglesFromVectors(angles, localnormal, NULL, false);
13256 AngleVectors(angles, planes[0], planes[2], planes[4]);
13257 VectorNegate(planes[0], planes[1]);
13258 VectorNegate(planes[2], planes[3]);
13259 VectorNegate(planes[4], planes[5]);
13260 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13261 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13262 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13263 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13264 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13265 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13270 matrix4x4_t forwardprojection;
13271 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13272 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13277 float projectionvector[4][3];
13278 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13279 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13280 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13281 projectionvector[0][0] = planes[0][0] * ilocalsize;
13282 projectionvector[0][1] = planes[1][0] * ilocalsize;
13283 projectionvector[0][2] = planes[2][0] * ilocalsize;
13284 projectionvector[1][0] = planes[0][1] * ilocalsize;
13285 projectionvector[1][1] = planes[1][1] * ilocalsize;
13286 projectionvector[1][2] = planes[2][1] * ilocalsize;
13287 projectionvector[2][0] = planes[0][2] * ilocalsize;
13288 projectionvector[2][1] = planes[1][2] * ilocalsize;
13289 projectionvector[2][2] = planes[2][2] * ilocalsize;
13290 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13291 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13292 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13293 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13297 dynamic = model->surfmesh.isanimated;
13298 numsurfacelist = model->nummodelsurfaces;
13299 surfacelist = model->sortedmodelsurfaces;
13300 surfaces = model->data_surfaces;
13303 bih_triangles_count = -1;
13306 if(model->render_bih.numleafs)
13307 bih = &model->render_bih;
13308 else if(model->collision_bih.numleafs)
13309 bih = &model->collision_bih;
13312 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13313 if(bih_triangles_count == 0)
13315 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13317 if(bih_triangles_count > 0)
13319 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13321 surfaceindex = bih_surfaces[triangleindex];
13322 surface = surfaces + surfaceindex;
13323 texture = surface->texture;
13324 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13326 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13328 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13333 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13335 surfaceindex = surfacelist[surfacelistindex];
13336 surface = surfaces + surfaceindex;
13337 // check cull box first because it rejects more than any other check
13338 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13340 // skip transparent surfaces
13341 texture = surface->texture;
13342 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13344 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13346 numtriangles = surface->num_triangles;
13347 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13348 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13353 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13354 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)
13356 int renderentityindex;
13357 float worldmins[3];
13358 float worldmaxs[3];
13359 entity_render_t *ent;
13361 if (!cl_decals_newsystem.integer)
13364 worldmins[0] = worldorigin[0] - worldsize;
13365 worldmins[1] = worldorigin[1] - worldsize;
13366 worldmins[2] = worldorigin[2] - worldsize;
13367 worldmaxs[0] = worldorigin[0] + worldsize;
13368 worldmaxs[1] = worldorigin[1] + worldsize;
13369 worldmaxs[2] = worldorigin[2] + worldsize;
13371 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13373 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13375 ent = r_refdef.scene.entities[renderentityindex];
13376 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13379 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13383 typedef struct r_decalsystem_splatqueue_s
13385 vec3_t worldorigin;
13386 vec3_t worldnormal;
13392 r_decalsystem_splatqueue_t;
13394 int r_decalsystem_numqueued = 0;
13395 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13397 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)
13399 r_decalsystem_splatqueue_t *queue;
13401 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13404 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13405 VectorCopy(worldorigin, queue->worldorigin);
13406 VectorCopy(worldnormal, queue->worldnormal);
13407 Vector4Set(queue->color, r, g, b, a);
13408 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13409 queue->worldsize = worldsize;
13410 queue->decalsequence = cl.decalsequence++;
13413 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13416 r_decalsystem_splatqueue_t *queue;
13418 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13419 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);
13420 r_decalsystem_numqueued = 0;
13423 extern cvar_t cl_decals_max;
13424 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13427 decalsystem_t *decalsystem = &ent->decalsystem;
13434 if (!decalsystem->numdecals)
13437 if (r_showsurfaces.integer)
13440 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13442 R_DecalSystem_Reset(decalsystem);
13446 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13447 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13449 if (decalsystem->lastupdatetime)
13450 frametime = (cl.time - decalsystem->lastupdatetime);
13453 decalsystem->lastupdatetime = cl.time;
13454 decal = decalsystem->decals;
13455 numdecals = decalsystem->numdecals;
13457 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13459 if (decal->color4ub[0][3])
13461 decal->lived += frametime;
13462 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13464 memset(decal, 0, sizeof(*decal));
13465 if (decalsystem->freedecal > i)
13466 decalsystem->freedecal = i;
13470 decal = decalsystem->decals;
13471 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13474 // collapse the array by shuffling the tail decals into the gaps
13477 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13478 decalsystem->freedecal++;
13479 if (decalsystem->freedecal == numdecals)
13481 decal[decalsystem->freedecal] = decal[--numdecals];
13484 decalsystem->numdecals = numdecals;
13486 if (numdecals <= 0)
13488 // if there are no decals left, reset decalsystem
13489 R_DecalSystem_Reset(decalsystem);
13493 extern skinframe_t *decalskinframe;
13494 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13497 decalsystem_t *decalsystem = &ent->decalsystem;
13506 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13509 numdecals = decalsystem->numdecals;
13513 if (r_showsurfaces.integer)
13516 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13518 R_DecalSystem_Reset(decalsystem);
13522 // if the model is static it doesn't matter what value we give for
13523 // wantnormals and wanttangents, so this logic uses only rules applicable
13524 // to a model, knowing that they are meaningless otherwise
13525 if (ent == r_refdef.scene.worldentity)
13526 RSurf_ActiveWorldEntity();
13528 RSurf_ActiveModelEntity(ent, false, false, false);
13530 decalsystem->lastupdatetime = cl.time;
13531 decal = decalsystem->decals;
13533 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13535 // update vertex positions for animated models
13536 v3f = decalsystem->vertex3f;
13537 c4f = decalsystem->color4f;
13538 t2f = decalsystem->texcoord2f;
13539 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13541 if (!decal->color4ub[0][3])
13544 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13547 // update color values for fading decals
13548 if (decal->lived >= cl_decals_time.value)
13550 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13551 alpha *= (1.0f/255.0f);
13554 alpha = 1.0f/255.0f;
13556 c4f[ 0] = decal->color4ub[0][0] * alpha;
13557 c4f[ 1] = decal->color4ub[0][1] * alpha;
13558 c4f[ 2] = decal->color4ub[0][2] * alpha;
13560 c4f[ 4] = decal->color4ub[1][0] * alpha;
13561 c4f[ 5] = decal->color4ub[1][1] * alpha;
13562 c4f[ 6] = decal->color4ub[1][2] * alpha;
13564 c4f[ 8] = decal->color4ub[2][0] * alpha;
13565 c4f[ 9] = decal->color4ub[2][1] * alpha;
13566 c4f[10] = decal->color4ub[2][2] * alpha;
13569 t2f[0] = decal->texcoord2f[0][0];
13570 t2f[1] = decal->texcoord2f[0][1];
13571 t2f[2] = decal->texcoord2f[1][0];
13572 t2f[3] = decal->texcoord2f[1][1];
13573 t2f[4] = decal->texcoord2f[2][0];
13574 t2f[5] = decal->texcoord2f[2][1];
13576 // update vertex positions for animated models
13577 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13579 e = rsurface.modelelement3i + 3*decal->triangleindex;
13580 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13581 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13582 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13586 VectorCopy(decal->vertex3f[0], v3f);
13587 VectorCopy(decal->vertex3f[1], v3f + 3);
13588 VectorCopy(decal->vertex3f[2], v3f + 6);
13591 if (r_refdef.fogenabled)
13593 alpha = RSurf_FogVertex(v3f);
13594 VectorScale(c4f, alpha, c4f);
13595 alpha = RSurf_FogVertex(v3f + 3);
13596 VectorScale(c4f + 4, alpha, c4f + 4);
13597 alpha = RSurf_FogVertex(v3f + 6);
13598 VectorScale(c4f + 8, alpha, c4f + 8);
13609 r_refdef.stats.drawndecals += numtris;
13611 // now render the decals all at once
13612 // (this assumes they all use one particle font texture!)
13613 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);
13614 R_Mesh_ResetTextureState();
13615 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13616 GL_DepthMask(false);
13617 GL_DepthRange(0, 1);
13618 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13619 GL_DepthTest(true);
13620 GL_CullFace(GL_NONE);
13621 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13622 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13623 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13627 static void R_DrawModelDecals(void)
13631 // fade faster when there are too many decals
13632 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13633 for (i = 0;i < r_refdef.scene.numentities;i++)
13634 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13636 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13637 for (i = 0;i < r_refdef.scene.numentities;i++)
13638 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13639 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13641 R_DecalSystem_ApplySplatEntitiesQueue();
13643 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13644 for (i = 0;i < r_refdef.scene.numentities;i++)
13645 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13647 r_refdef.stats.totaldecals += numdecals;
13649 if (r_showsurfaces.integer)
13652 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13654 for (i = 0;i < r_refdef.scene.numentities;i++)
13656 if (!r_refdef.viewcache.entityvisible[i])
13658 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13659 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13663 extern cvar_t mod_collision_bih;
13664 void R_DrawDebugModel(void)
13666 entity_render_t *ent = rsurface.entity;
13667 int i, j, k, l, flagsmask;
13668 const msurface_t *surface;
13669 dp_model_t *model = ent->model;
13672 switch(vid.renderpath)
13674 case RENDERPATH_GL11:
13675 case RENDERPATH_GL13:
13676 case RENDERPATH_GL20:
13677 case RENDERPATH_CGGL:
13679 case RENDERPATH_D3D9:
13680 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13682 case RENDERPATH_D3D10:
13683 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13685 case RENDERPATH_D3D11:
13686 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13690 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13692 R_Mesh_ResetTextureState();
13693 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13694 GL_DepthRange(0, 1);
13695 GL_DepthTest(!r_showdisabledepthtest.integer);
13696 GL_DepthMask(false);
13697 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13699 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13703 qboolean cullbox = ent == r_refdef.scene.worldentity;
13704 const q3mbrush_t *brush;
13705 const bih_t *bih = &model->collision_bih;
13706 const bih_leaf_t *bihleaf;
13707 float vertex3f[3][3];
13708 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13710 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13712 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13714 switch (bihleaf->type)
13717 brush = model->brush.data_brushes + bihleaf->itemindex;
13718 if (brush->colbrushf && brush->colbrushf->numtriangles)
13720 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13721 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13722 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13725 case BIH_COLLISIONTRIANGLE:
13726 triangleindex = bihleaf->itemindex;
13727 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13728 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13729 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13730 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13731 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13732 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13734 case BIH_RENDERTRIANGLE:
13735 triangleindex = bihleaf->itemindex;
13736 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13737 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13738 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13739 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13740 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13741 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13747 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13749 if (r_showtris.integer || r_shownormals.integer)
13751 if (r_showdisabledepthtest.integer)
13753 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13754 GL_DepthMask(false);
13758 GL_BlendFunc(GL_ONE, GL_ZERO);
13759 GL_DepthMask(true);
13761 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13763 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13765 rsurface.texture = R_GetCurrentTexture(surface->texture);
13766 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13768 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13769 if (r_showtris.value > 0)
13771 if (!rsurface.texture->currentlayers->depthmask)
13772 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13773 else if (ent == r_refdef.scene.worldentity)
13774 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13776 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13777 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13778 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13780 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13783 if (r_shownormals.value < 0)
13785 qglBegin(GL_LINES);
13786 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13788 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13789 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13790 qglVertex3f(v[0], v[1], v[2]);
13791 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13792 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13793 qglVertex3f(v[0], v[1], v[2]);
13798 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13800 qglBegin(GL_LINES);
13801 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13803 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13804 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13805 qglVertex3f(v[0], v[1], v[2]);
13806 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13807 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13808 qglVertex3f(v[0], v[1], v[2]);
13812 qglBegin(GL_LINES);
13813 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13815 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13816 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13817 qglVertex3f(v[0], v[1], v[2]);
13818 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13819 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13820 qglVertex3f(v[0], v[1], v[2]);
13824 qglBegin(GL_LINES);
13825 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13827 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13828 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13829 qglVertex3f(v[0], v[1], v[2]);
13830 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13831 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13832 qglVertex3f(v[0], v[1], v[2]);
13839 rsurface.texture = NULL;
13843 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13844 int r_maxsurfacelist = 0;
13845 const msurface_t **r_surfacelist = NULL;
13846 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13848 int i, j, endj, flagsmask;
13849 dp_model_t *model = r_refdef.scene.worldmodel;
13850 msurface_t *surfaces;
13851 unsigned char *update;
13852 int numsurfacelist = 0;
13856 if (r_maxsurfacelist < model->num_surfaces)
13858 r_maxsurfacelist = model->num_surfaces;
13860 Mem_Free((msurface_t**)r_surfacelist);
13861 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13864 RSurf_ActiveWorldEntity();
13866 surfaces = model->data_surfaces;
13867 update = model->brushq1.lightmapupdateflags;
13869 // update light styles on this submodel
13870 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13872 model_brush_lightstyleinfo_t *style;
13873 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13875 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13877 int *list = style->surfacelist;
13878 style->value = r_refdef.scene.lightstylevalue[style->style];
13879 for (j = 0;j < style->numsurfaces;j++)
13880 update[list[j]] = true;
13885 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13889 R_DrawDebugModel();
13890 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13894 rsurface.lightmaptexture = NULL;
13895 rsurface.deluxemaptexture = NULL;
13896 rsurface.uselightmaptexture = false;
13897 rsurface.texture = NULL;
13898 rsurface.rtlight = NULL;
13899 numsurfacelist = 0;
13900 // add visible surfaces to draw list
13901 for (i = 0;i < model->nummodelsurfaces;i++)
13903 j = model->sortedmodelsurfaces[i];
13904 if (r_refdef.viewcache.world_surfacevisible[j])
13905 r_surfacelist[numsurfacelist++] = surfaces + j;
13907 // update lightmaps if needed
13908 if (model->brushq1.firstrender)
13910 model->brushq1.firstrender = false;
13911 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13913 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13917 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13918 if (r_refdef.viewcache.world_surfacevisible[j])
13920 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13922 // don't do anything if there were no surfaces
13923 if (!numsurfacelist)
13925 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13928 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13929 GL_AlphaTest(false);
13931 // add to stats if desired
13932 if (r_speeds.integer && !skysurfaces && !depthonly)
13934 r_refdef.stats.world_surfaces += numsurfacelist;
13935 for (j = 0;j < numsurfacelist;j++)
13936 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13939 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13942 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13944 int i, j, endj, flagsmask;
13945 dp_model_t *model = ent->model;
13946 msurface_t *surfaces;
13947 unsigned char *update;
13948 int numsurfacelist = 0;
13952 if (r_maxsurfacelist < model->num_surfaces)
13954 r_maxsurfacelist = model->num_surfaces;
13956 Mem_Free((msurface_t **)r_surfacelist);
13957 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13960 // if the model is static it doesn't matter what value we give for
13961 // wantnormals and wanttangents, so this logic uses only rules applicable
13962 // to a model, knowing that they are meaningless otherwise
13963 if (ent == r_refdef.scene.worldentity)
13964 RSurf_ActiveWorldEntity();
13965 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13966 RSurf_ActiveModelEntity(ent, false, false, false);
13968 RSurf_ActiveModelEntity(ent, true, true, true);
13969 else if (depthonly)
13971 switch (vid.renderpath)
13973 case RENDERPATH_GL20:
13974 case RENDERPATH_CGGL:
13975 case RENDERPATH_D3D9:
13976 case RENDERPATH_D3D10:
13977 case RENDERPATH_D3D11:
13978 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13980 case RENDERPATH_GL13:
13981 case RENDERPATH_GL11:
13982 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13988 switch (vid.renderpath)
13990 case RENDERPATH_GL20:
13991 case RENDERPATH_CGGL:
13992 case RENDERPATH_D3D9:
13993 case RENDERPATH_D3D10:
13994 case RENDERPATH_D3D11:
13995 RSurf_ActiveModelEntity(ent, true, true, false);
13997 case RENDERPATH_GL13:
13998 case RENDERPATH_GL11:
13999 RSurf_ActiveModelEntity(ent, true, false, false);
14004 surfaces = model->data_surfaces;
14005 update = model->brushq1.lightmapupdateflags;
14007 // update light styles
14008 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14010 model_brush_lightstyleinfo_t *style;
14011 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14013 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14015 int *list = style->surfacelist;
14016 style->value = r_refdef.scene.lightstylevalue[style->style];
14017 for (j = 0;j < style->numsurfaces;j++)
14018 update[list[j]] = true;
14023 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14027 R_DrawDebugModel();
14028 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14032 rsurface.lightmaptexture = NULL;
14033 rsurface.deluxemaptexture = NULL;
14034 rsurface.uselightmaptexture = false;
14035 rsurface.texture = NULL;
14036 rsurface.rtlight = NULL;
14037 numsurfacelist = 0;
14038 // add visible surfaces to draw list
14039 for (i = 0;i < model->nummodelsurfaces;i++)
14040 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14041 // don't do anything if there were no surfaces
14042 if (!numsurfacelist)
14044 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14047 // update lightmaps if needed
14051 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14056 R_BuildLightMap(ent, surfaces + j);
14061 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14063 R_BuildLightMap(ent, surfaces + j);
14064 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14065 GL_AlphaTest(false);
14067 // add to stats if desired
14068 if (r_speeds.integer && !skysurfaces && !depthonly)
14070 r_refdef.stats.entities_surfaces += numsurfacelist;
14071 for (j = 0;j < numsurfacelist;j++)
14072 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14075 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14078 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14080 static texture_t texture;
14081 static msurface_t surface;
14082 const msurface_t *surfacelist = &surface;
14084 // fake enough texture and surface state to render this geometry
14086 texture.update_lastrenderframe = -1; // regenerate this texture
14087 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14088 texture.currentskinframe = skinframe;
14089 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14090 texture.offsetmapping = OFFSETMAPPING_OFF;
14091 texture.offsetscale = 1;
14092 texture.specularscalemod = 1;
14093 texture.specularpowermod = 1;
14095 surface.texture = &texture;
14096 surface.num_triangles = numtriangles;
14097 surface.num_firsttriangle = firsttriangle;
14098 surface.num_vertices = numvertices;
14099 surface.num_firstvertex = firstvertex;
14102 rsurface.texture = R_GetCurrentTexture(surface.texture);
14103 rsurface.lightmaptexture = NULL;
14104 rsurface.deluxemaptexture = NULL;
14105 rsurface.uselightmaptexture = false;
14106 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14109 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)
14111 static msurface_t surface;
14112 const msurface_t *surfacelist = &surface;
14114 // fake enough texture and surface state to render this geometry
14116 surface.texture = texture;
14117 surface.num_triangles = numtriangles;
14118 surface.num_firsttriangle = firsttriangle;
14119 surface.num_vertices = numvertices;
14120 surface.num_firstvertex = firstvertex;
14123 rsurface.texture = R_GetCurrentTexture(surface.texture);
14124 rsurface.lightmaptexture = NULL;
14125 rsurface.deluxemaptexture = NULL;
14126 rsurface.uselightmaptexture = false;
14127 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);