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 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
591 "# extension GL_ARB_texture_rectangle : enable\n"
594 "#ifdef USESHADOWMAP2D\n"
595 "# ifdef GL_EXT_gpu_shader4\n"
596 "# extension GL_EXT_gpu_shader4 : enable\n"
598 "# ifdef GL_ARB_texture_gather\n"
599 "# extension GL_ARB_texture_gather : enable\n"
601 "# ifdef GL_AMD_texture_texture4\n"
602 "# extension GL_AMD_texture_texture4 : enable\n"
607 "#ifdef USESHADOWMAPCUBE\n"
608 "# extension GL_EXT_gpu_shader4 : enable\n"
611 "//#ifdef USESHADOWSAMPLER\n"
612 "//# extension GL_ARB_shadow : enable\n"
615 "//#ifdef __GLSL_CG_DATA_TYPES\n"
616 "//# define myhalf half\n"
617 "//# define myhalf2 half2\n"
618 "//# define myhalf3 half3\n"
619 "//# define myhalf4 half4\n"
621 "# define myhalf float\n"
622 "# define myhalf2 vec2\n"
623 "# define myhalf3 vec3\n"
624 "# define myhalf4 vec4\n"
627 "#ifdef VERTEX_SHADER\n"
628 "uniform mat4 ModelViewProjectionMatrix;\n"
631 "#ifdef MODE_DEPTH_OR_SHADOW\n"
632 "#ifdef VERTEX_SHADER\n"
635 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
638 "#else // !MODE_DEPTH_ORSHADOW\n"
643 "#ifdef MODE_SHOWDEPTH\n"
644 "#ifdef VERTEX_SHADER\n"
647 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
652 "#ifdef FRAGMENT_SHADER\n"
655 " gl_FragColor = gl_Color;\n"
658 "#else // !MODE_SHOWDEPTH\n"
663 "#ifdef MODE_POSTPROCESS\n"
664 "varying vec2 TexCoord1;\n"
665 "varying vec2 TexCoord2;\n"
667 "#ifdef VERTEX_SHADER\n"
670 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
673 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
678 "#ifdef FRAGMENT_SHADER\n"
679 "uniform sampler2D Texture_First;\n"
681 "uniform sampler2D Texture_Second;\n"
682 "uniform vec4 BloomColorSubtract;\n"
684 "#ifdef USEGAMMARAMPS\n"
685 "uniform sampler2D Texture_GammaRamps;\n"
687 "#ifdef USESATURATION\n"
688 "uniform float Saturation;\n"
690 "#ifdef USEVIEWTINT\n"
691 "uniform vec4 ViewTintColor;\n"
693 "//uncomment these if you want to use them:\n"
694 "uniform vec4 UserVec1;\n"
695 "uniform vec4 UserVec2;\n"
696 "// uniform vec4 UserVec3;\n"
697 "// uniform vec4 UserVec4;\n"
698 "// uniform float ClientTime;\n"
699 "uniform vec2 PixelSize;\n"
702 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
704 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
706 "#ifdef USEVIEWTINT\n"
707 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
710 "#ifdef USEPOSTPROCESSING\n"
711 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
712 "// 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"
713 " float sobel = 1.0;\n"
714 " // vec2 ts = textureSize(Texture_First, 0);\n"
715 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
716 " vec2 px = PixelSize;\n"
717 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
718 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
719 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
720 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
721 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
722 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
724 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
725 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
728 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
729 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
730 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
731 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
732 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
733 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
734 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
735 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
736 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
737 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
738 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
739 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
740 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
741 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
742 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
743 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
744 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
745 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
746 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
747 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
748 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
751 "#ifdef USESATURATION\n"
752 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
753 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
754 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
758 "#ifdef USEGAMMARAMPS\n"
759 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
760 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
761 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
765 "#else // !MODE_POSTPROCESS\n"
770 "#ifdef MODE_GENERIC\n"
771 "#ifdef USEDIFFUSE\n"
772 "varying vec2 TexCoord1;\n"
774 "#ifdef USESPECULAR\n"
775 "varying vec2 TexCoord2;\n"
777 "#ifdef VERTEX_SHADER\n"
780 " gl_FrontColor = gl_Color;\n"
781 "#ifdef USEDIFFUSE\n"
782 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
784 "#ifdef USESPECULAR\n"
785 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
787 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
791 "#ifdef FRAGMENT_SHADER\n"
792 "#ifdef USEDIFFUSE\n"
793 "uniform sampler2D Texture_First;\n"
795 "#ifdef USESPECULAR\n"
796 "uniform sampler2D Texture_Second;\n"
801 " gl_FragColor = gl_Color;\n"
802 "#ifdef USEDIFFUSE\n"
803 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
806 "#ifdef USESPECULAR\n"
807 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
808 "# ifdef USECOLORMAPPING\n"
809 " gl_FragColor *= tex2;\n"
812 " gl_FragColor += tex2;\n"
814 "# ifdef USEVERTEXTEXTUREBLEND\n"
815 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
820 "#else // !MODE_GENERIC\n"
825 "#ifdef MODE_BLOOMBLUR\n"
826 "varying TexCoord;\n"
827 "#ifdef VERTEX_SHADER\n"
830 " gl_FrontColor = gl_Color;\n"
831 " TexCoord = gl_MultiTexCoord0.xy;\n"
832 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
836 "#ifdef FRAGMENT_SHADER\n"
837 "uniform sampler2D Texture_First;\n"
838 "uniform vec4 BloomBlur_Parameters;\n"
843 " vec2 tc = TexCoord;\n"
844 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
845 " tc += BloomBlur_Parameters.xy;\n"
846 " for (i = 1;i < SAMPLES;i++)\n"
848 " color += texture2D(Texture_First, tc).rgb;\n"
849 " tc += BloomBlur_Parameters.xy;\n"
851 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
854 "#else // !MODE_BLOOMBLUR\n"
855 "#ifdef MODE_REFRACTION\n"
856 "varying vec2 TexCoord;\n"
857 "varying vec4 ModelViewProjectionPosition;\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef VERTEX_SHADER\n"
863 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
864 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
865 " ModelViewProjectionPosition = gl_Position;\n"
869 "#ifdef FRAGMENT_SHADER\n"
870 "uniform sampler2D Texture_Normal;\n"
871 "uniform sampler2D Texture_Refraction;\n"
872 "uniform sampler2D Texture_Reflection;\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform vec4 RefractColor;\n"
878 "uniform vec4 ReflectColor;\n"
879 "uniform float ReflectFactor;\n"
880 "uniform float ReflectOffset;\n"
884 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
885 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
886 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
888 " // FIXME temporary hack to detect the case that the reflection\n"
889 " // gets blackened at edges due to leaving the area that contains actual\n"
891 " // Remove this 'ack once we have a better way to stop this thing from\n"
893 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
894 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
895 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
896 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
897 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
898 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
901 "#else // !MODE_REFRACTION\n"
906 "#ifdef MODE_WATER\n"
907 "varying vec2 TexCoord;\n"
908 "varying vec3 EyeVector;\n"
909 "varying vec4 ModelViewProjectionPosition;\n"
910 "#ifdef VERTEX_SHADER\n"
911 "uniform vec3 EyePosition;\n"
912 "uniform mat4 TexMatrix;\n"
916 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
917 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
918 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
919 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
920 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
921 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
922 " ModelViewProjectionPosition = gl_Position;\n"
926 "#ifdef FRAGMENT_SHADER\n"
927 "uniform sampler2D Texture_Normal;\n"
928 "uniform sampler2D Texture_Refraction;\n"
929 "uniform sampler2D Texture_Reflection;\n"
931 "uniform vec4 DistortScaleRefractReflect;\n"
932 "uniform vec4 ScreenScaleRefractReflect;\n"
933 "uniform vec4 ScreenCenterRefractReflect;\n"
934 "uniform vec4 RefractColor;\n"
935 "uniform vec4 ReflectColor;\n"
936 "uniform float ReflectFactor;\n"
937 "uniform float ReflectOffset;\n"
941 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
942 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
943 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
944 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
945 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
946 " // FIXME temporary hack to detect the case that the reflection\n"
947 " // gets blackened at edges due to leaving the area that contains actual\n"
949 " // Remove this 'ack once we have a better way to stop this thing from\n"
951 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
952 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
953 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
954 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
955 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
956 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
957 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
958 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
959 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
960 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
961 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
962 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
965 "#else // !MODE_WATER\n"
970 "// common definitions between vertex shader and fragment shader:\n"
972 "varying vec2 TexCoord;\n"
973 "#ifdef USEVERTEXTEXTUREBLEND\n"
974 "varying vec2 TexCoord2;\n"
976 "#ifdef USELIGHTMAP\n"
977 "varying vec2 TexCoordLightmap;\n"
980 "#ifdef MODE_LIGHTSOURCE\n"
981 "varying vec3 CubeVector;\n"
984 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
985 "varying vec3 LightVector;\n"
988 "#ifdef USEEYEVECTOR\n"
989 "varying vec3 EyeVector;\n"
992 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
996 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
997 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
998 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1001 "#ifdef USEREFLECTION\n"
1002 "varying vec4 ModelViewProjectionPosition;\n"
1004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1005 "uniform vec3 LightPosition;\n"
1006 "varying vec4 ModelViewPosition;\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "uniform vec3 LightPosition;\n"
1012 "uniform vec3 EyePosition;\n"
1013 "#ifdef MODE_LIGHTDIRECTION\n"
1014 "uniform vec3 LightDir;\n"
1016 "uniform vec4 FogPlane;\n"
1018 "#ifdef USESHADOWMAPORTHO\n"
1019 "varying vec3 ShadowMapTC;\n"
1026 "// 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"
1028 "// fragment shader specific:\n"
1029 "#ifdef FRAGMENT_SHADER\n"
1031 "uniform sampler2D Texture_Normal;\n"
1032 "uniform sampler2D Texture_Color;\n"
1033 "uniform sampler2D Texture_Gloss;\n"
1035 "uniform sampler2D Texture_Glow;\n"
1037 "#ifdef USEVERTEXTEXTUREBLEND\n"
1038 "uniform sampler2D Texture_SecondaryNormal;\n"
1039 "uniform sampler2D Texture_SecondaryColor;\n"
1040 "uniform sampler2D Texture_SecondaryGloss;\n"
1042 "uniform sampler2D Texture_SecondaryGlow;\n"
1045 "#ifdef USECOLORMAPPING\n"
1046 "uniform sampler2D Texture_Pants;\n"
1047 "uniform sampler2D Texture_Shirt;\n"
1050 "#ifdef USEFOGHEIGHTTEXTURE\n"
1051 "uniform sampler2D Texture_FogHeightTexture;\n"
1053 "uniform sampler2D Texture_FogMask;\n"
1055 "#ifdef USELIGHTMAP\n"
1056 "uniform sampler2D Texture_Lightmap;\n"
1058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1059 "uniform sampler2D Texture_Deluxemap;\n"
1061 "#ifdef USEREFLECTION\n"
1062 "uniform sampler2D Texture_Reflection;\n"
1065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1066 "uniform sampler2D Texture_ScreenDepth;\n"
1067 "uniform sampler2D Texture_ScreenNormalMap;\n"
1069 "#ifdef USEDEFERREDLIGHTMAP\n"
1070 "uniform sampler2D Texture_ScreenDiffuse;\n"
1071 "uniform sampler2D Texture_ScreenSpecular;\n"
1074 "uniform myhalf3 Color_Pants;\n"
1075 "uniform myhalf3 Color_Shirt;\n"
1076 "uniform myhalf3 FogColor;\n"
1079 "uniform float FogRangeRecip;\n"
1080 "uniform float FogPlaneViewDist;\n"
1081 "uniform float FogHeightFade;\n"
1082 "vec3 FogVertex(vec3 surfacecolor)\n"
1084 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1085 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1087 "#ifdef USEFOGHEIGHTTEXTURE\n"
1088 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1089 " fogfrac = fogheightpixel.a;\n"
1090 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1092 "# ifdef USEFOGOUTSIDE\n"
1093 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1095 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1097 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 "uniform float OffsetMapping_Scale;\n"
1104 "vec2 OffsetMapping(vec2 TexCoord)\n"
1106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1107 " // 14 sample relief mapping: linear search and then binary search\n"
1108 " // this basically steps forward a small amount repeatedly until it finds\n"
1109 " // itself inside solid, then jitters forward and back using decreasing\n"
1110 " // amounts to find the impact\n"
1111 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1112 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1113 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1114 " vec3 RT = vec3(TexCoord, 1);\n"
1115 " OffsetVector *= 0.1;\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);\n"
1118 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1119 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1120 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1126 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1127 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1128 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1129 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1132 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1133 " // this basically moves forward the full distance, and then backs up based\n"
1134 " // on height of samples\n"
1135 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1136 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1137 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1138 " TexCoord += OffsetVector;\n"
1139 " OffsetVector *= 0.333;\n"
1140 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1141 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1142 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1143 " return TexCoord;\n"
1146 "#endif // USEOFFSETMAPPING\n"
1148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1149 "uniform sampler2D Texture_Attenuation;\n"
1150 "uniform samplerCube Texture_Cube;\n"
1153 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1155 "#ifdef USESHADOWMAPRECT\n"
1156 "# ifdef USESHADOWSAMPLER\n"
1157 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1159 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1163 "#ifdef USESHADOWMAP2D\n"
1164 "# ifdef USESHADOWSAMPLER\n"
1165 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1167 "uniform sampler2D Texture_ShadowMap2D;\n"
1171 "#ifdef USESHADOWMAPVSDCT\n"
1172 "uniform samplerCube Texture_CubeProjection;\n"
1175 "#ifdef USESHADOWMAPCUBE\n"
1176 "# ifdef USESHADOWSAMPLER\n"
1177 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1179 "uniform samplerCube Texture_ShadowMapCube;\n"
1183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1184 "uniform vec2 ShadowMap_TextureScale;\n"
1185 "uniform vec4 ShadowMap_Parameters;\n"
1188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1189 "# ifdef USESHADOWMAPORTHO\n"
1190 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1192 "# ifdef USESHADOWMAPVSDCT\n"
1193 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1195 " vec3 adir = abs(dir);\n"
1196 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1197 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1198 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1201 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1203 " vec3 adir = abs(dir);\n"
1204 " float ma = adir.z;\n"
1205 " vec4 proj = vec4(dir, 2.5);\n"
1206 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1207 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1208 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1209 " 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"
1213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1215 "#ifdef USESHADOWMAPCUBE\n"
1216 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1218 " vec3 adir = abs(dir);\n"
1219 " return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1223 "# ifdef USESHADOWMAPRECT\n"
1224 "float ShadowMapCompare(vec3 dir)\n"
1226 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1228 "# ifdef USESHADOWSAMPLER\n"
1230 "# ifdef USESHADOWMAPPCF\n"
1231 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1232 " 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"
1234 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1239 "# ifdef USESHADOWMAPPCF\n"
1240 "# if USESHADOWMAPPCF > 1\n"
1241 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1242 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 " 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"
1244 " 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"
1245 " 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"
1246 " 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"
1247 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1248 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1250 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1251 " vec2 offset = fract(shadowmaptc.xy);\n"
1252 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1253 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1254 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1255 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1256 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1259 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1263 "# ifdef USESHADOWMAPORTHO\n"
1264 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1271 "# ifdef USESHADOWMAP2D\n"
1272 "float ShadowMapCompare(vec3 dir)\n"
1274 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1277 "# ifdef USESHADOWSAMPLER\n"
1278 "# ifdef USESHADOWMAPPCF\n"
1279 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1280 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1281 " 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"
1283 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1286 "# ifdef USESHADOWMAPPCF\n"
1287 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1288 "# ifdef GL_ARB_texture_gather\n"
1289 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1291 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1293 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1294 "# if USESHADOWMAPPCF > 1\n"
1295 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1296 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1297 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1298 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1299 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1300 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1301 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1302 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1303 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1304 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1305 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1306 " locols.yz += group2.ab;\n"
1307 " hicols.yz += group8.rg;\n"
1308 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1309 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1310 " mix(locols, hicols, offset.y);\n"
1311 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1312 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1313 " f = dot(cols, vec4(1.0/25.0));\n"
1315 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1316 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1317 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1318 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1319 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1320 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1321 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1324 "# ifdef GL_EXT_gpu_shader4\n"
1325 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1327 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1329 "# if USESHADOWMAPPCF > 1\n"
1330 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1331 " center *= ShadowMap_TextureScale;\n"
1332 " 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"
1333 " 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"
1334 " 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"
1335 " 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"
1336 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1337 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1339 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1340 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1341 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1342 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1343 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1344 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1348 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1351 "# ifdef USESHADOWMAPORTHO\n"
1352 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1359 "# ifdef USESHADOWMAPCUBE\n"
1360 "float ShadowMapCompare(vec3 dir)\n"
1362 " // apply depth texture cubemap as light filter\n"
1363 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1365 "# ifdef USESHADOWSAMPLER\n"
1366 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1368 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1373 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1374 "#endif // FRAGMENT_SHADER\n"
1379 "#ifdef MODE_DEFERREDGEOMETRY\n"
1380 "#ifdef VERTEX_SHADER\n"
1381 "uniform mat4 TexMatrix;\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "uniform mat4 BackgroundTexMatrix;\n"
1385 "uniform mat4 ModelViewMatrix;\n"
1388 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 " gl_FrontColor = gl_Color;\n"
1391 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1394 " // transform unnormalized eye direction into tangent space\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1397 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1398 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1399 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1402 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1403 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1404 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1405 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1407 "#endif // VERTEX_SHADER\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1412 "#ifdef USEOFFSETMAPPING\n"
1413 " // apply offsetmapping\n"
1414 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1415 "#define TexCoord TexCoordOffset\n"
1418 "#ifdef USEALPHAKILL\n"
1419 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1425 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1426 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1427 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1432 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1434 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1435 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1438 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1440 "#endif // FRAGMENT_SHADER\n"
1441 "#else // !MODE_DEFERREDGEOMETRY\n"
1446 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1447 "#ifdef VERTEX_SHADER\n"
1448 "uniform mat4 ModelViewMatrix;\n"
1451 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1452 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1454 "#endif // VERTEX_SHADER\n"
1456 "#ifdef FRAGMENT_SHADER\n"
1457 "uniform mat4 ViewToLight;\n"
1458 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1459 "uniform vec2 ScreenToDepth;\n"
1460 "uniform myhalf3 DeferredColor_Ambient;\n"
1461 "uniform myhalf3 DeferredColor_Diffuse;\n"
1462 "#ifdef USESPECULAR\n"
1463 "uniform myhalf3 DeferredColor_Specular;\n"
1464 "uniform myhalf SpecularPower;\n"
1466 "uniform myhalf2 PixelToScreenTexCoord;\n"
1469 " // calculate viewspace pixel position\n"
1470 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1472 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1473 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1474 " // decode viewspace pixel normal\n"
1475 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1476 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1477 " // surfacenormal = pixel normal in viewspace\n"
1478 " // LightVector = pixel to light in viewspace\n"
1479 " // CubeVector = position in lightspace\n"
1480 " // eyevector = pixel to view in viewspace\n"
1481 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1482 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1483 "#ifdef USEDIFFUSE\n"
1484 " // calculate diffuse shading\n"
1485 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1486 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1488 "#ifdef USESPECULAR\n"
1489 " // calculate directional shading\n"
1490 " vec3 eyevector = position * -1.0;\n"
1491 "# ifdef USEEXACTSPECULARMATH\n"
1492 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1494 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1495 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1499 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1500 " fade *= ShadowMapCompare(CubeVector);\n"
1503 "#ifdef USEDIFFUSE\n"
1504 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1506 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1508 "#ifdef USESPECULAR\n"
1509 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1511 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1514 "# ifdef USECUBEFILTER\n"
1515 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1516 " gl_FragData[0].rgb *= cubecolor;\n"
1517 " gl_FragData[1].rgb *= cubecolor;\n"
1520 "#endif // FRAGMENT_SHADER\n"
1521 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1526 "#ifdef VERTEX_SHADER\n"
1527 "uniform mat4 TexMatrix;\n"
1528 "#ifdef USEVERTEXTEXTUREBLEND\n"
1529 "uniform mat4 BackgroundTexMatrix;\n"
1531 "#ifdef MODE_LIGHTSOURCE\n"
1532 "uniform mat4 ModelToLight;\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "uniform mat4 ShadowMapMatrix;\n"
1539 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1540 " gl_FrontColor = gl_Color;\n"
1542 " // copy the surface texcoord\n"
1543 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1547 "#ifdef USELIGHTMAP\n"
1548 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1551 "#ifdef MODE_LIGHTSOURCE\n"
1552 " // transform vertex position into light attenuation/cubemap space\n"
1553 " // (-1 to +1 across the light box)\n"
1554 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1556 "# ifdef USEDIFFUSE\n"
1557 " // transform unnormalized light direction into tangent space\n"
1558 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1559 " // normalize it per pixel)\n"
1560 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1561 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1562 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1563 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1567 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1568 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1569 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1570 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1573 " // transform unnormalized eye direction into tangent space\n"
1574 "#ifdef USEEYEVECTOR\n"
1575 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1576 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1577 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1578 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1582 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1583 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1586 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1587 " VectorS = gl_MultiTexCoord1.xyz;\n"
1588 " VectorT = gl_MultiTexCoord2.xyz;\n"
1589 " VectorR = gl_MultiTexCoord3.xyz;\n"
1592 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1593 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1595 "#ifdef USESHADOWMAPORTHO\n"
1596 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1599 "#ifdef USEREFLECTION\n"
1600 " ModelViewProjectionPosition = gl_Position;\n"
1603 "#endif // VERTEX_SHADER\n"
1608 "#ifdef FRAGMENT_SHADER\n"
1609 "#ifdef USEDEFERREDLIGHTMAP\n"
1610 "uniform myhalf2 PixelToScreenTexCoord;\n"
1611 "uniform myhalf3 DeferredMod_Diffuse;\n"
1612 "uniform myhalf3 DeferredMod_Specular;\n"
1614 "uniform myhalf3 Color_Ambient;\n"
1615 "uniform myhalf3 Color_Diffuse;\n"
1616 "uniform myhalf3 Color_Specular;\n"
1617 "uniform myhalf SpecularPower;\n"
1619 "uniform myhalf3 Color_Glow;\n"
1621 "uniform myhalf Alpha;\n"
1622 "#ifdef USEREFLECTION\n"
1623 "uniform vec4 DistortScaleRefractReflect;\n"
1624 "uniform vec4 ScreenScaleRefractReflect;\n"
1625 "uniform vec4 ScreenCenterRefractReflect;\n"
1626 "uniform myhalf4 ReflectColor;\n"
1628 "#ifdef USEREFLECTCUBE\n"
1629 "uniform mat4 ModelToReflectCube;\n"
1630 "uniform sampler2D Texture_ReflectMask;\n"
1631 "uniform samplerCube Texture_ReflectCube;\n"
1633 "#ifdef MODE_LIGHTDIRECTION\n"
1634 "uniform myhalf3 LightColor;\n"
1636 "#ifdef MODE_LIGHTSOURCE\n"
1637 "uniform myhalf3 LightColor;\n"
1641 "#ifdef USEOFFSETMAPPING\n"
1642 " // apply offsetmapping\n"
1643 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1644 "#define TexCoord TexCoordOffset\n"
1647 " // combine the diffuse textures (base, pants, shirt)\n"
1648 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1649 "#ifdef USEALPHAKILL\n"
1650 " if (color.a < 0.5)\n"
1653 " color.a *= Alpha;\n"
1654 "#ifdef USECOLORMAPPING\n"
1655 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1657 "#ifdef USEVERTEXTEXTUREBLEND\n"
1658 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1659 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1660 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1661 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1663 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1666 " // get the surface normal\n"
1667 "#ifdef USEVERTEXTEXTUREBLEND\n"
1668 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1670 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1673 " // get the material colors\n"
1674 " myhalf3 diffusetex = color.rgb;\n"
1675 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1676 "# ifdef USEVERTEXTEXTUREBLEND\n"
1677 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1679 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1683 "#ifdef USEREFLECTCUBE\n"
1684 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1685 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1686 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1687 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 " // light source\n"
1695 "#ifdef USEDIFFUSE\n"
1696 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1697 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1698 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1699 "#ifdef USESPECULAR\n"
1700 "#ifdef USEEXACTSPECULARMATH\n"
1701 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1703 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1704 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1706 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1709 " color.rgb = diffusetex * Color_Ambient;\n"
1711 " color.rgb *= LightColor;\n"
1712 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1713 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1714 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1716 "# ifdef USECUBEFILTER\n"
1717 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1719 "#endif // MODE_LIGHTSOURCE\n"
1724 "#ifdef MODE_LIGHTDIRECTION\n"
1726 "#ifdef USEDIFFUSE\n"
1727 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1729 "#define lightcolor LightColor\n"
1730 "#endif // MODE_LIGHTDIRECTION\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1733 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1734 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 " // convert modelspace light vector to tangentspace\n"
1737 " myhalf3 lightnormal;\n"
1738 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1739 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1740 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1741 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1742 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1743 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1744 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1745 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1746 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1747 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1748 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1749 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1750 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1751 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1754 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1755 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1756 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1762 "#ifdef MODE_LIGHTMAP\n"
1763 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1764 "#endif // MODE_LIGHTMAP\n"
1765 "#ifdef MODE_VERTEXCOLOR\n"
1766 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1767 "#endif // MODE_VERTEXCOLOR\n"
1768 "#ifdef MODE_FLATCOLOR\n"
1769 " color.rgb = diffusetex * Color_Ambient;\n"
1770 "#endif // MODE_FLATCOLOR\n"
1776 "# ifdef USEDIFFUSE\n"
1777 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1778 "# ifdef USESPECULAR\n"
1779 "# ifdef USEEXACTSPECULARMATH\n"
1780 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1782 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1783 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1785 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1787 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1790 " color.rgb = diffusetex * Color_Ambient;\n"
1794 "#ifdef USESHADOWMAPORTHO\n"
1795 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1798 "#ifdef USEDEFERREDLIGHTMAP\n"
1799 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1800 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1801 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1805 "#ifdef USEVERTEXTEXTUREBLEND\n"
1806 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1808 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1813 " color.rgb = FogVertex(color.rgb);\n"
1816 " // 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"
1817 "#ifdef USEREFLECTION\n"
1818 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1819 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1820 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1821 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1822 " // FIXME temporary hack to detect the case that the reflection\n"
1823 " // gets blackened at edges due to leaving the area that contains actual\n"
1825 " // Remove this 'ack once we have a better way to stop this thing from\n"
1827 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1828 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1829 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1830 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1831 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1832 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1835 " gl_FragColor = vec4(color);\n"
1837 "#endif // FRAGMENT_SHADER\n"
1839 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1840 "#endif // !MODE_DEFERREDGEOMETRY\n"
1841 "#endif // !MODE_WATER\n"
1842 "#endif // !MODE_REFRACTION\n"
1843 "#endif // !MODE_BLOOMBLUR\n"
1844 "#endif // !MODE_GENERIC\n"
1845 "#endif // !MODE_POSTPROCESS\n"
1846 "#endif // !MODE_SHOWDEPTH\n"
1847 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1851 =========================================================================================================================================================
1855 =========================================================================================================================================================
1859 =========================================================================================================================================================
1863 =========================================================================================================================================================
1867 =========================================================================================================================================================
1871 =========================================================================================================================================================
1875 =========================================================================================================================================================
1878 const char *builtincgshaderstring =
1879 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1880 "// written by Forest 'LordHavoc' Hale\n"
1881 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1883 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1884 "#if defined(USEREFLECTION)\n"
1885 "#undef USESHADOWMAPORTHO\n"
1888 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1891 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1892 "#define USELIGHTMAP\n"
1894 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1895 "#define USEEYEVECTOR\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1900 "//#undef USESHADOWMAPPCF\n"
1901 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1902 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1904 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1908 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1909 "#ifdef VERTEX_SHADER\n"
1912 "float4 gl_Vertex : POSITION,\n"
1913 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float Depth : TEXCOORD0\n"
1918 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 " Depth = gl_Position.z;\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1926 "float Depth : TEXCOORD0,\n"
1927 "out float4 gl_FragColor : COLOR\n"
1930 "// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1931 " float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1932 " temp.yz -= floor(temp.yz);\n"
1933 " gl_FragColor = float4(temp,0);\n"
1934 "// gl_FragColor = float4(Depth,0,0,0);\n"
1937 "#else // !MODE_DEPTH_ORSHADOW\n"
1942 "#ifdef MODE_SHOWDEPTH\n"
1943 "#ifdef VERTEX_SHADER\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float4 gl_FrontColor : COLOR0\n"
1952 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1960 "float4 gl_FrontColor : COLOR0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1964 " gl_FragColor = gl_FrontColor;\n"
1967 "#else // !MODE_SHOWDEPTH\n"
1972 "#ifdef MODE_POSTPROCESS\n"
1974 "#ifdef VERTEX_SHADER\n"
1977 "float4 gl_Vertex : POSITION,\n"
1978 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1979 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1980 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1981 "out float4 gl_Position : POSITION,\n"
1982 "out float2 TexCoord1 : TEXCOORD0,\n"
1983 "out float2 TexCoord2 : TEXCOORD1\n"
1986 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1989 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1997 "float2 TexCoord1 : TEXCOORD0,\n"
1998 "float2 TexCoord2 : TEXCOORD1,\n"
1999 "uniform sampler Texture_First : register(s0),\n"
2001 "uniform sampler Texture_Second : register(s1),\n"
2003 "#ifdef USEGAMMARAMPS\n"
2004 "uniform sampler Texture_GammaRamps : register(s2),\n"
2006 "#ifdef USESATURATION\n"
2007 "uniform float Saturation : register(c30),\n"
2009 "#ifdef USEVIEWTINT\n"
2010 "uniform float4 ViewTintColor : register(c41),\n"
2012 "uniform float4 UserVec1 : register(c37),\n"
2013 "uniform float4 UserVec2 : register(c38),\n"
2014 "uniform float4 UserVec3 : register(c39),\n"
2015 "uniform float4 UserVec4 : register(c40),\n"
2016 "uniform float ClientTime : register(c2),\n"
2017 "uniform float2 PixelSize : register(c25),\n"
2018 "uniform float4 BloomColorSubtract : register(c43),\n"
2019 "out float4 gl_FragColor : COLOR\n"
2022 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2024 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2026 "#ifdef USEVIEWTINT\n"
2027 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2030 "#ifdef USEPOSTPROCESSING\n"
2031 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2032 "// 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"
2033 " float sobel = 1.0;\n"
2034 " // float2 ts = textureSize(Texture_First, 0);\n"
2035 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
2036 " float2 px = PixelSize;\n"
2037 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2038 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
2039 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2040 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2041 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
2042 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2043 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2044 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
2045 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2046 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2047 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
2048 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2049 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2050 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2051 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2052 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2053 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2054 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2055 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2056 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2057 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2058 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2059 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2060 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2061 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2062 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2063 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2064 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2065 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2066 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2067 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2068 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2071 "#ifdef USESATURATION\n"
2072 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2073 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2074 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2075 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2085 "#else // !MODE_POSTPROCESS\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "out float4 gl_FrontColor : COLOR,\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "out float2 TexCoord2 : TEXCOORD1\n"
2106 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2108 " gl_FrontColor = gl_Color; // Cg is forward\n"
2110 "#ifdef USEDIFFUSE\n"
2111 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2113 "#ifdef USESPECULAR\n"
2114 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2116 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2133 "out float4 gl_FragColor : COLOR\n"
2136 " gl_FragColor = gl_FrontColor;\n"
2137 "#ifdef USEDIFFUSE\n"
2138 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2141 "#ifdef USESPECULAR\n"
2142 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2143 "# ifdef USECOLORMAPPING\n"
2144 " gl_FragColor *= tex2;\n"
2147 " gl_FragColor += tex2;\n"
2149 "# ifdef USEVERTEXTEXTUREBLEND\n"
2150 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2155 "#else // !MODE_GENERIC\n"
2160 "#ifdef MODE_BLOOMBLUR\n"
2161 "#ifdef VERTEX_SHADER\n"
2164 "float4 gl_Vertex : POSITION,\n"
2165 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2166 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2167 "out float4 gl_Position : POSITION,\n"
2168 "out float2 TexCoord : TEXCOORD0\n"
2171 " TexCoord = gl_MultiTexCoord0.xy;\n"
2172 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2180 "float2 TexCoord : TEXCOORD0,\n"
2181 "uniform sampler Texture_First : register(s0),\n"
2182 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2183 "out float4 gl_FragColor : COLOR\n"
2187 " float2 tc = TexCoord;\n"
2188 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2189 " tc += BloomBlur_Parameters.xy;\n"
2190 " for (i = 1;i < SAMPLES;i++)\n"
2192 " color += tex2D(Texture_First, tc).rgb;\n"
2193 " tc += BloomBlur_Parameters.xy;\n"
2195 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2198 "#else // !MODE_BLOOMBLUR\n"
2199 "#ifdef MODE_REFRACTION\n"
2200 "#ifdef VERTEX_SHADER\n"
2203 "float4 gl_Vertex : POSITION,\n"
2204 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2205 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2206 "uniform float4x4 TexMatrix : register(c0),\n"
2207 "uniform float3 EyePosition : register(c24),\n"
2208 "out float4 gl_Position : POSITION,\n"
2209 "out float2 TexCoord : TEXCOORD0,\n"
2210 "out float3 EyeVector : TEXCOORD1,\n"
2211 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2214 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2215 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2216 " ModelViewProjectionPosition = gl_Position;\n"
2220 "#ifdef FRAGMENT_SHADER\n"
2223 "float2 TexCoord : TEXCOORD0,\n"
2224 "float3 EyeVector : TEXCOORD1,\n"
2225 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2226 "uniform sampler Texture_Normal : register(s0),\n"
2227 "uniform sampler Texture_Refraction : register(s3),\n"
2228 "uniform sampler Texture_Reflection : register(s7),\n"
2229 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2230 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2231 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2232 "uniform float4 RefractColor : register(c29),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2236 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2237 " //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"
2238 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2239 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2240 " // FIXME temporary hack to detect the case that the reflection\n"
2241 " // gets blackened at edges due to leaving the area that contains actual\n"
2243 " // Remove this 'ack once we have a better way to stop this thing from\n"
2245 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2250 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2253 "#else // !MODE_REFRACTION\n"
2258 "#ifdef MODE_WATER\n"
2259 "#ifdef VERTEX_SHADER\n"
2263 "float4 gl_Vertex : POSITION,\n"
2264 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2265 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2266 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2267 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2268 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2269 "uniform float4x4 TexMatrix : register(c0),\n"
2270 "uniform float3 EyePosition : register(c24),\n"
2271 "out float4 gl_Position : POSITION,\n"
2272 "out float2 TexCoord : TEXCOORD0,\n"
2273 "out float3 EyeVector : TEXCOORD1,\n"
2274 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2277 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2278 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2279 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2280 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2281 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2282 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2283 " ModelViewProjectionPosition = gl_Position;\n"
2287 "#ifdef FRAGMENT_SHADER\n"
2290 "float2 TexCoord : TEXCOORD0,\n"
2291 "float3 EyeVector : TEXCOORD1,\n"
2292 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2293 "uniform sampler Texture_Normal : register(s0),\n"
2294 "uniform sampler Texture_Refraction : register(s3),\n"
2295 "uniform sampler Texture_Reflection : register(s7),\n"
2296 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2297 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2298 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2299 "uniform float4 RefractColor : register(c29),\n"
2300 "uniform float4 ReflectColor : register(c26),\n"
2301 "uniform float ReflectFactor : register(c27),\n"
2302 "uniform float ReflectOffset : register(c28),\n"
2303 "out float4 gl_FragColor : COLOR\n"
2306 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2307 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2308 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2309 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2310 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2311 " // FIXME temporary hack to detect the case that the reflection\n"
2312 " // gets blackened at edges due to leaving the area that contains actual\n"
2314 " // Remove this 'ack once we have a better way to stop this thing from\n"
2316 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2317 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2318 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2319 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2320 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2321 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2322 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2323 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2324 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2325 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2326 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2327 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2330 "#else // !MODE_WATER\n"
2335 "// 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"
2337 "// fragment shader specific:\n"
2338 "#ifdef FRAGMENT_SHADER\n"
2341 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2344 "#ifdef USEFOGHEIGHTTEXTURE\n"
2345 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2346 " fogfrac = fogheightpixel.a;\n"
2347 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2349 "# ifdef USEFOGOUTSIDE\n"
2350 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2352 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2354 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2359 "#ifdef USEOFFSETMAPPING\n"
2360 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2362 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2363 " // 14 sample relief mapping: linear search and then binary search\n"
2364 " // this basically steps forward a small amount repeatedly until it finds\n"
2365 " // itself inside solid, then jitters forward and back using decreasing\n"
2366 " // amounts to find the impact\n"
2367 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2368 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2369 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2370 " float3 RT = float3(TexCoord, 1);\n"
2371 " OffsetVector *= 0.1;\n"
2372 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2373 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2374 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2375 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2376 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2382 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2383 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2384 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2385 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2388 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2389 " // this basically moves forward the full distance, and then backs up based\n"
2390 " // on height of samples\n"
2391 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2392 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2393 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2394 " TexCoord += OffsetVector;\n"
2395 " OffsetVector *= 0.333;\n"
2396 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2397 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2398 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2399 " return TexCoord;\n"
2402 "#endif // USEOFFSETMAPPING\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2409 "# ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2412 " float3 adir = abs(dir);\n"
2413 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2420 " float3 adir = abs(dir);\n"
2421 " float ma = adir.z;\n"
2422 " float4 proj = float4(dir, 2.5);\n"
2423 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2426 " 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"
2428 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 " 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"
2434 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2436 "#ifdef USESHADOWMAPCUBE\n"
2437 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2439 " float3 adir = abs(dir);\n"
2440 " return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2444 "# ifdef USESHADOWMAPRECT\n"
2445 "#ifdef USESHADOWMAPVSDCT\n"
2446 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2448 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2451 "#ifdef USESHADOWMAPVSDCT\n"
2452 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2454 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2457 "# ifdef USESHADOWSAMPLER\n"
2459 "# ifdef USESHADOWMAPPCF\n"
2460 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2461 " 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"
2463 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2468 "# ifdef USESHADOWMAPPCF\n"
2469 "# if USESHADOWMAPPCF > 1\n"
2470 "# define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2471 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2472 " 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"
2473 " 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"
2474 " 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"
2475 " 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"
2476 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2479 "# define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2480 " float2 offset = frac(shadowmaptc.xy);\n"
2481 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2482 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2483 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2484 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2485 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2488 " f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2492 "# ifdef USESHADOWMAPORTHO\n"
2493 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2500 "# ifdef USESHADOWMAP2D\n"
2501 "#ifdef USESHADOWMAPVSDCT\n"
2502 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2504 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2507 "#ifdef USESHADOWMAPVSDCT\n"
2508 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2510 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2514 "# ifdef USESHADOWSAMPLER\n"
2515 "# ifdef USESHADOWMAPPCF\n"
2516 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2517 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2518 " 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"
2520 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2523 "# ifdef USESHADOWMAPPCF\n"
2524 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2525 "# ifdef GL_ARB_texture_gather\n"
2526 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2528 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2530 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2531 "# if USESHADOWMAPPCF > 1\n"
2532 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2533 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2534 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2535 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2536 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2537 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2538 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2539 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2540 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2541 " float4 locols = float4(group1.ab, group3.ab);\n"
2542 " float4 hicols = float4(group7.rg, group9.rg);\n"
2543 " locols.yz += group2.ab;\n"
2544 " hicols.yz += group8.rg;\n"
2545 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2546 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2547 " lerp(locols, hicols, offset.y);\n"
2548 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2549 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2550 " f = dot(cols, float4(1.0/25.0));\n"
2552 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2553 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2554 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2555 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2556 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2557 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2558 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2561 "# ifdef GL_EXT_gpu_shader4\n"
2562 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2564 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2566 "# if USESHADOWMAPPCF > 1\n"
2567 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2568 " center *= ShadowMap_TextureScale;\n"
2569 " 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"
2570 " 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"
2571 " 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"
2572 " 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"
2573 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2574 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2576 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2577 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2578 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2579 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2580 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2581 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2585 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2588 "# ifdef USESHADOWMAPORTHO\n"
2589 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2596 "# ifdef USESHADOWMAPCUBE\n"
2597 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2599 " // apply depth texture cubemap as light filter\n"
2600 " float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2602 "# ifdef USESHADOWSAMPLER\n"
2603 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2605 " f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2610 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2611 "#endif // FRAGMENT_SHADER\n"
2616 "#ifdef MODE_DEFERREDGEOMETRY\n"
2617 "#ifdef VERTEX_SHADER\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "#ifdef USEVERTEXTEXTUREBLEND\n"
2623 "float4 gl_Color : COLOR0,\n"
2625 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2626 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2627 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2628 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2629 "uniform float4x4 TexMatrix : register(c0),\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2633 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2634 "#ifdef USEOFFSETMAPPING\n"
2635 "uniform float3 EyePosition : register(c24),\n"
2637 "out float4 gl_Position : POSITION,\n"
2638 "out float4 gl_FrontColor : COLOR,\n"
2639 "out float4 TexCoordBoth : TEXCOORD0,\n"
2640 "#ifdef USEOFFSETMAPPING\n"
2641 "out float3 EyeVector : TEXCOORD2,\n"
2643 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2644 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2645 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2648 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2651 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2653 " gl_FrontColor = gl_Color; // Cg is forward\n"
2655 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2658 " // transform unnormalized eye direction into tangent space\n"
2659 "#ifdef USEOFFSETMAPPING\n"
2660 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2661 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2662 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2663 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2666 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2667 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2668 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2669 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2671 "#endif // VERTEX_SHADER\n"
2673 "#ifdef FRAGMENT_SHADER\n"
2676 "float4 TexCoordBoth : TEXCOORD0,\n"
2677 "float3 EyeVector : TEXCOORD2,\n"
2678 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "uniform sampler Texture_Normal : register(s0),\n"
2682 "#ifdef USEALPHAKILL\n"
2683 "uniform sampler Texture_Color : register(s1),\n"
2685 "uniform sampler Texture_Gloss : register(s2),\n"
2686 "#ifdef USEVERTEXTEXTUREBLEND\n"
2687 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2688 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2690 "#ifdef USEOFFSETMAPPING\n"
2691 "uniform float OffsetMapping_Scale : register(c24),\n"
2693 "uniform half SpecularPower : register(c36),\n"
2694 "out float4 gl_FragColor : COLOR\n"
2697 " float2 TexCoord = TexCoordBoth.xy;\n"
2698 "#ifdef USEOFFSETMAPPING\n"
2699 " // apply offsetmapping\n"
2700 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2701 "#define TexCoord TexCoordOffset\n"
2704 "#ifdef USEALPHAKILL\n"
2705 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2709 "#ifdef USEVERTEXTEXTUREBLEND\n"
2710 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2711 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2712 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2713 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2716 "#ifdef USEVERTEXTEXTUREBLEND\n"
2717 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2718 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2720 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2721 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2724 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2726 "#endif // FRAGMENT_SHADER\n"
2727 "#else // !MODE_DEFERREDGEOMETRY\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "#ifdef VERTEX_SHADER\n"
2736 "float4 gl_Vertex : POSITION,\n"
2737 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2738 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2739 "out float4 gl_Position : POSITION,\n"
2740 "out float4 ModelViewPosition : TEXCOORD0\n"
2743 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2744 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2746 "#endif // VERTEX_SHADER\n"
2748 "#ifdef FRAGMENT_SHADER\n"
2752 "float2 Pixel : VPOS,\n"
2754 "float2 Pixel : WPOS,\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "uniform float4x4 ViewToLight : register(c44),\n"
2758 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2759 "uniform float3 LightPosition : register(c23),\n"
2760 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2761 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2762 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2763 "#ifdef USESPECULAR\n"
2764 "uniform half3 DeferredColor_Specular : register(c11),\n"
2765 "uniform half SpecularPower : register(c36),\n"
2767 "uniform sampler Texture_Attenuation : register(s9),\n"
2768 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2769 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2771 "#ifdef USECUBEFILTER\n"
2772 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2775 "#ifdef USESHADOWMAPRECT\n"
2776 "# ifdef USESHADOWSAMPLER\n"
2777 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2779 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2783 "#ifdef USESHADOWMAP2D\n"
2784 "# ifdef USESHADOWSAMPLER\n"
2785 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2787 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2791 "#ifdef USESHADOWMAPVSDCT\n"
2792 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2795 "#ifdef USESHADOWMAPCUBE\n"
2796 "# ifdef USESHADOWSAMPLER\n"
2797 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2799 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2803 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2804 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2805 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2808 "out float4 gl_FragData0 : COLOR0,\n"
2809 "out float4 gl_FragData1 : COLOR1\n"
2812 " // calculate viewspace pixel position\n"
2813 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2814 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2815 " float3 position;\n"
2816 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2817 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2818 " // decode viewspace pixel normal\n"
2819 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2820 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2821 " // surfacenormal = pixel normal in viewspace\n"
2822 " // LightVector = pixel to light in viewspace\n"
2823 " // CubeVector = position in lightspace\n"
2824 " // eyevector = pixel to view in viewspace\n"
2825 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2826 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2827 "#ifdef USEDIFFUSE\n"
2828 " // calculate diffuse shading\n"
2829 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2830 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2832 "#ifdef USESPECULAR\n"
2833 " // calculate directional shading\n"
2834 " float3 eyevector = position * -1.0;\n"
2835 "# ifdef USEEXACTSPECULARMATH\n"
2836 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2838 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2839 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2843 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2844 " fade *= ShadowMapCompare(CubeVector,\n"
2845 "# if defined(USESHADOWMAP2D)\n"
2846 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2848 "# if defined(USESHADOWMAPRECT)\n"
2849 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2851 "# if defined(USESHADOWMAPCUBE)\n"
2852 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2855 "#ifdef USESHADOWMAPVSDCT\n"
2856 ", Texture_CubeProjection\n"
2861 "#ifdef USEDIFFUSE\n"
2862 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2864 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2866 "#ifdef USESPECULAR\n"
2867 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2869 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2872 "# ifdef USECUBEFILTER\n"
2873 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2874 " gl_FragData0.rgb *= cubecolor;\n"
2875 " gl_FragData1.rgb *= cubecolor;\n"
2878 "#endif // FRAGMENT_SHADER\n"
2879 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2884 "#ifdef VERTEX_SHADER\n"
2887 "float4 gl_Vertex : POSITION,\n"
2888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2889 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2890 "float4 gl_Color : COLOR0,\n"
2892 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2893 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2894 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2895 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2896 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2898 "uniform float3 EyePosition : register(c24),\n"
2899 "uniform float4x4 TexMatrix : register(c0),\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2903 "#ifdef MODE_LIGHTSOURCE\n"
2904 "uniform float4x4 ModelToLight : register(c20),\n"
2906 "#ifdef MODE_LIGHTSOURCE\n"
2907 "uniform float3 LightPosition : register(c27),\n"
2909 "#ifdef MODE_LIGHTDIRECTION\n"
2910 "uniform float3 LightDir : register(c26),\n"
2912 "uniform float4 FogPlane : register(c25),\n"
2913 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2914 "uniform float3 LightPosition : register(c27),\n"
2916 "#ifdef USESHADOWMAPORTHO\n"
2917 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2920 "out float4 gl_FrontColor : COLOR,\n"
2921 "out float4 TexCoordBoth : TEXCOORD0,\n"
2922 "#ifdef USELIGHTMAP\n"
2923 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2925 "#ifdef USEEYEVECTOR\n"
2926 "out float3 EyeVector : TEXCOORD2,\n"
2928 "#ifdef USEREFLECTION\n"
2929 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2932 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2935 "out float3 LightVector : TEXCOORD1,\n"
2937 "#ifdef MODE_LIGHTSOURCE\n"
2938 "out float3 CubeVector : TEXCOORD3,\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2948 "out float4 gl_Position : POSITION\n"
2951 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2953 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2955 " gl_FrontColor = gl_Color; // Cg is forward\n"
2958 " // copy the surface texcoord\n"
2959 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2960 "#ifdef USEVERTEXTEXTUREBLEND\n"
2961 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2963 "#ifdef USELIGHTMAP\n"
2964 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2967 "#ifdef MODE_LIGHTSOURCE\n"
2968 " // transform vertex position into light attenuation/cubemap space\n"
2969 " // (-1 to +1 across the light box)\n"
2970 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2972 "# ifdef USEDIFFUSE\n"
2973 " // transform unnormalized light direction into tangent space\n"
2974 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2975 " // normalize it per pixel)\n"
2976 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2977 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2978 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2979 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2983 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2984 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2985 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2986 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2989 " // transform unnormalized eye direction into tangent space\n"
2990 "#ifdef USEEYEVECTOR\n"
2991 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2992 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2993 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2994 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2998 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2999 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 " VectorS = gl_MultiTexCoord1.xyz;\n"
3004 " VectorT = gl_MultiTexCoord2.xyz;\n"
3005 " VectorR = gl_MultiTexCoord3.xyz;\n"
3008 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3009 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3011 "#ifdef USESHADOWMAPORTHO\n"
3012 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3015 "#ifdef USEREFLECTION\n"
3016 " ModelViewProjectionPosition = gl_Position;\n"
3019 "#endif // VERTEX_SHADER\n"
3024 "#ifdef FRAGMENT_SHADER\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3029 "float2 Pixel : VPOS,\n"
3031 "float2 Pixel : WPOS,\n"
3034 "float4 gl_FrontColor : COLOR,\n"
3035 "float4 TexCoordBoth : TEXCOORD0,\n"
3036 "#ifdef USELIGHTMAP\n"
3037 "float2 TexCoordLightmap : TEXCOORD1,\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "float3 EyeVector : TEXCOORD2,\n"
3042 "#ifdef USEREFLECTION\n"
3043 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3046 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3049 "float3 LightVector : TEXCOORD1,\n"
3051 "#ifdef MODE_LIGHTSOURCE\n"
3052 "float3 CubeVector : TEXCOORD3,\n"
3054 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3055 "float4 ModelViewPosition : TEXCOORD0,\n"
3057 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3058 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3059 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3060 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3062 "#ifdef USESHADOWMAPORTHO\n"
3063 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3066 "uniform sampler Texture_Normal : register(s0),\n"
3067 "uniform sampler Texture_Color : register(s1),\n"
3068 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3069 "uniform sampler Texture_Gloss : register(s2),\n"
3072 "uniform sampler Texture_Glow : register(s3),\n"
3074 "#ifdef USEVERTEXTEXTUREBLEND\n"
3075 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3076 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3077 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3078 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3081 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3084 "#ifdef USECOLORMAPPING\n"
3085 "uniform sampler Texture_Pants : register(s4),\n"
3086 "uniform sampler Texture_Shirt : register(s7),\n"
3089 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3090 "uniform sampler Texture_FogMask : register(s8),\n"
3092 "#ifdef USELIGHTMAP\n"
3093 "uniform sampler Texture_Lightmap : register(s9),\n"
3095 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3096 "uniform sampler Texture_Deluxemap : register(s10),\n"
3098 "#ifdef USEREFLECTION\n"
3099 "uniform sampler Texture_Reflection : register(s7),\n"
3102 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3103 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3104 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3106 "#ifdef USEDEFERREDLIGHTMAP\n"
3107 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3108 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3111 "#ifdef USECOLORMAPPING\n"
3112 "uniform half3 Color_Pants : register(c7),\n"
3113 "uniform half3 Color_Shirt : register(c8),\n"
3116 "uniform float3 FogColor : register(c16),\n"
3117 "uniform float FogRangeRecip : register(c20),\n"
3118 "uniform float FogPlaneViewDist : register(c19),\n"
3119 "uniform float FogHeightFade : register(c17),\n"
3122 "#ifdef USEOFFSETMAPPING\n"
3123 "uniform float OffsetMapping_Scale : register(c24),\n"
3126 "#ifdef USEDEFERREDLIGHTMAP\n"
3127 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3128 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3129 "uniform half3 DeferredMod_Specular : register(c13),\n"
3131 "uniform half3 Color_Ambient : register(c3),\n"
3132 "uniform half3 Color_Diffuse : register(c4),\n"
3133 "uniform half3 Color_Specular : register(c5),\n"
3134 "uniform half SpecularPower : register(c36),\n"
3136 "uniform half3 Color_Glow : register(c6),\n"
3138 "uniform half Alpha : register(c0),\n"
3139 "#ifdef USEREFLECTION\n"
3140 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3141 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3142 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3143 "uniform half4 ReflectColor : register(c26),\n"
3145 "#ifdef USEREFLECTCUBE\n"
3146 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3147 "uniform sampler Texture_ReflectMask : register(s5),\n"
3148 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3150 "#ifdef MODE_LIGHTDIRECTION\n"
3151 "uniform half3 LightColor : register(c21),\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "uniform half3 LightColor : register(c21),\n"
3157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3158 "uniform sampler Texture_Attenuation : register(s9),\n"
3159 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3162 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3164 "#ifdef USESHADOWMAPRECT\n"
3165 "# ifdef USESHADOWSAMPLER\n"
3166 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3168 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3172 "#ifdef USESHADOWMAP2D\n"
3173 "# ifdef USESHADOWSAMPLER\n"
3174 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3176 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3180 "#ifdef USESHADOWMAPVSDCT\n"
3181 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3184 "#ifdef USESHADOWMAPCUBE\n"
3185 "# ifdef USESHADOWSAMPLER\n"
3186 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3188 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3193 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3194 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3196 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3198 "out float4 gl_FragColor : COLOR\n"
3201 " float2 TexCoord = TexCoordBoth.xy;\n"
3202 "#ifdef USEVERTEXTEXTUREBLEND\n"
3203 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3205 "#ifdef USEOFFSETMAPPING\n"
3206 " // apply offsetmapping\n"
3207 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3208 "#define TexCoord TexCoordOffset\n"
3211 " // combine the diffuse textures (base, pants, shirt)\n"
3212 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3213 "#ifdef USEALPHAKILL\n"
3214 " if (color.a < 0.5)\n"
3217 " color.a *= Alpha;\n"
3218 "#ifdef USECOLORMAPPING\n"
3219 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3221 "#ifdef USEVERTEXTEXTUREBLEND\n"
3222 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3223 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3224 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3225 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3227 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3230 " // get the surface normal\n"
3231 "#ifdef USEVERTEXTEXTUREBLEND\n"
3232 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3234 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3237 " // get the material colors\n"
3238 " half3 diffusetex = color.rgb;\n"
3239 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3240 "# ifdef USEVERTEXTEXTUREBLEND\n"
3241 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3243 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3247 "#ifdef USEREFLECTCUBE\n"
3248 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3249 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3250 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3251 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3257 "#ifdef MODE_LIGHTSOURCE\n"
3258 " // light source\n"
3259 "#ifdef USEDIFFUSE\n"
3260 " half3 lightnormal = half3(normalize(LightVector));\n"
3261 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3262 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3263 "#ifdef USESPECULAR\n"
3264 "#ifdef USEEXACTSPECULARMATH\n"
3265 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3267 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3268 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3270 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3273 " color.rgb = diffusetex * Color_Ambient;\n"
3275 " color.rgb *= LightColor;\n"
3276 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3277 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3278 " color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3279 "# if defined(USESHADOWMAP2D)\n"
3280 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3282 "# if defined(USESHADOWMAPRECT)\n"
3283 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3285 "# if defined(USESHADOWMAPCUBE)\n"
3286 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3289 "#ifdef USESHADOWMAPVSDCT\n"
3290 ", Texture_CubeProjection\n"
3295 "# ifdef USECUBEFILTER\n"
3296 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3299 "#ifdef USESHADOWMAP2D\n"
3300 "#ifdef USESHADOWMAPVSDCT\n"
3301 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3302 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3303 "// color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3304 "// color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3306 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3307 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3308 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3309 "// color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3310 "// color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3311 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3312 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3313 "// color.r = half(shadowmaptc.z);\n"
3317 "// color.rgb = half3(1,1,1);\n"
3318 "#endif // MODE_LIGHTSOURCE\n"
3323 "#ifdef MODE_LIGHTDIRECTION\n"
3325 "#ifdef USEDIFFUSE\n"
3326 " half3 lightnormal = half3(normalize(LightVector));\n"
3328 "#define lightcolor LightColor\n"
3329 "#endif // MODE_LIGHTDIRECTION\n"
3330 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3332 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3333 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3334 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3335 " // convert modelspace light vector to tangentspace\n"
3336 " half3 lightnormal;\n"
3337 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3338 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3339 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3340 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3341 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3342 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3343 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3344 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3345 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3346 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3347 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3348 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3349 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3350 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3351 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3353 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3354 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3355 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3361 "#ifdef MODE_LIGHTMAP\n"
3362 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3363 "#endif // MODE_LIGHTMAP\n"
3364 "#ifdef MODE_VERTEXCOLOR\n"
3365 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3366 "#endif // MODE_VERTEXCOLOR\n"
3367 "#ifdef MODE_FLATCOLOR\n"
3368 " color.rgb = diffusetex * Color_Ambient;\n"
3369 "#endif // MODE_FLATCOLOR\n"
3375 "# ifdef USEDIFFUSE\n"
3376 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3377 "# ifdef USESPECULAR\n"
3378 "# ifdef USEEXACTSPECULARMATH\n"
3379 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3381 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3382 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3384 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3386 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3389 " color.rgb = diffusetex * Color_Ambient;\n"
3393 "#ifdef USESHADOWMAPORTHO\n"
3394 " color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3395 "# if defined(USESHADOWMAP2D)\n"
3396 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3398 "# if defined(USESHADOWMAPRECT)\n"
3399 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3404 "#ifdef USEDEFERREDLIGHTMAP\n"
3405 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3406 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3407 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3411 "#ifdef USEVERTEXTEXTUREBLEND\n"
3412 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3414 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3419 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3422 " // 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"
3423 "#ifdef USEREFLECTION\n"
3424 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3425 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3426 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3427 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3428 " // FIXME temporary hack to detect the case that the reflection\n"
3429 " // gets blackened at edges due to leaving the area that contains actual\n"
3431 " // Remove this 'ack once we have a better way to stop this thing from\n"
3433 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3434 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3435 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3436 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3437 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3438 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3441 " gl_FragColor = float4(color);\n"
3443 "#endif // FRAGMENT_SHADER\n"
3445 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3446 "#endif // !MODE_DEFERREDGEOMETRY\n"
3447 "#endif // !MODE_WATER\n"
3448 "#endif // !MODE_REFRACTION\n"
3449 "#endif // !MODE_BLOOMBLUR\n"
3450 "#endif // !MODE_GENERIC\n"
3451 "#endif // !MODE_POSTPROCESS\n"
3452 "#endif // !MODE_SHOWDEPTH\n"
3453 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3456 char *glslshaderstring = NULL;
3457 char *cgshaderstring = NULL;
3458 char *hlslshaderstring = NULL;
3460 //=======================================================================================================================================================
3462 typedef struct shaderpermutationinfo_s
3464 const char *pretext;
3467 shaderpermutationinfo_t;
3469 typedef struct shadermodeinfo_s
3471 const char *vertexfilename;
3472 const char *geometryfilename;
3473 const char *fragmentfilename;
3474 const char *pretext;
3479 typedef enum shaderpermutation_e
3481 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3482 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3483 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3484 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3485 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3486 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3487 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3488 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3489 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3490 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3491 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3492 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3493 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3494 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3495 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3496 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3497 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3498 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3499 SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3500 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3501 SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3502 SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3503 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3504 SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3505 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3506 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3507 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3508 SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3509 SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3510 SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3511 SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3513 shaderpermutation_t;
3515 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3516 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3518 {"#define USEDIFFUSE\n", " diffuse"},
3519 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3520 {"#define USEVIEWTINT\n", " viewtint"},
3521 {"#define USECOLORMAPPING\n", " colormapping"},
3522 {"#define USESATURATION\n", " saturation"},
3523 {"#define USEFOGINSIDE\n", " foginside"},
3524 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3525 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3526 {"#define USEGAMMARAMPS\n", " gammaramps"},
3527 {"#define USECUBEFILTER\n", " cubefilter"},
3528 {"#define USEGLOW\n", " glow"},
3529 {"#define USEBLOOM\n", " bloom"},
3530 {"#define USESPECULAR\n", " specular"},
3531 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3532 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3533 {"#define USEREFLECTION\n", " reflection"},
3534 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3535 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3536 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3537 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3538 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3539 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3540 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3541 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3542 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3543 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3544 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3545 {"#define USEALPHAKILL\n", " alphakill"},
3546 {"#define USEREFLECTCUBE\n", " reflectcube"},
3549 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3550 typedef enum shadermode_e
3552 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3553 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3554 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3555 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3556 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3557 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3558 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3559 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3560 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3561 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3562 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3563 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3564 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3565 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3566 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3571 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3572 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3574 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3575 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3576 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3577 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3578 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3579 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3580 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3581 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3582 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3583 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3584 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3585 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3586 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3587 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3588 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3592 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3594 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3595 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3596 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3597 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3598 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3599 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3600 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3601 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3602 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3603 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3604 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3605 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3606 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3607 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3608 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3613 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3615 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3616 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3617 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3618 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3619 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3620 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3621 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3622 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3623 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3624 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3625 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3626 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3627 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3628 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3629 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3633 struct r_glsl_permutation_s;
3634 typedef struct r_glsl_permutation_s
3636 /// hash lookup data
3637 struct r_glsl_permutation_s *hashnext;
3639 unsigned int permutation;
3641 /// indicates if we have tried compiling this permutation already
3643 /// 0 if compilation failed
3645 /// locations of detected uniforms in program object, or -1 if not found
3646 int loc_Texture_First;
3647 int loc_Texture_Second;
3648 int loc_Texture_GammaRamps;
3649 int loc_Texture_Normal;
3650 int loc_Texture_Color;
3651 int loc_Texture_Gloss;
3652 int loc_Texture_Glow;
3653 int loc_Texture_SecondaryNormal;
3654 int loc_Texture_SecondaryColor;
3655 int loc_Texture_SecondaryGloss;
3656 int loc_Texture_SecondaryGlow;
3657 int loc_Texture_Pants;
3658 int loc_Texture_Shirt;
3659 int loc_Texture_FogHeightTexture;
3660 int loc_Texture_FogMask;
3661 int loc_Texture_Lightmap;
3662 int loc_Texture_Deluxemap;
3663 int loc_Texture_Attenuation;
3664 int loc_Texture_Cube;
3665 int loc_Texture_Refraction;
3666 int loc_Texture_Reflection;
3667 int loc_Texture_ShadowMapRect;
3668 int loc_Texture_ShadowMapCube;
3669 int loc_Texture_ShadowMap2D;
3670 int loc_Texture_CubeProjection;
3671 int loc_Texture_ScreenDepth;
3672 int loc_Texture_ScreenNormalMap;
3673 int loc_Texture_ScreenDiffuse;
3674 int loc_Texture_ScreenSpecular;
3675 int loc_Texture_ReflectMask;
3676 int loc_Texture_ReflectCube;
3678 int loc_BloomBlur_Parameters;
3680 int loc_Color_Ambient;
3681 int loc_Color_Diffuse;
3682 int loc_Color_Specular;
3684 int loc_Color_Pants;
3685 int loc_Color_Shirt;
3686 int loc_DeferredColor_Ambient;
3687 int loc_DeferredColor_Diffuse;
3688 int loc_DeferredColor_Specular;
3689 int loc_DeferredMod_Diffuse;
3690 int loc_DeferredMod_Specular;
3691 int loc_DistortScaleRefractReflect;
3692 int loc_EyePosition;
3694 int loc_FogHeightFade;
3696 int loc_FogPlaneViewDist;
3697 int loc_FogRangeRecip;
3700 int loc_LightPosition;
3701 int loc_OffsetMapping_Scale;
3703 int loc_ReflectColor;
3704 int loc_ReflectFactor;
3705 int loc_ReflectOffset;
3706 int loc_RefractColor;
3708 int loc_ScreenCenterRefractReflect;
3709 int loc_ScreenScaleRefractReflect;
3710 int loc_ScreenToDepth;
3711 int loc_ShadowMap_Parameters;
3712 int loc_ShadowMap_TextureScale;
3713 int loc_SpecularPower;
3718 int loc_ViewTintColor;
3719 int loc_ViewToLight;
3720 int loc_ModelToLight;
3722 int loc_BackgroundTexMatrix;
3723 int loc_ModelViewProjectionMatrix;
3724 int loc_ModelViewMatrix;
3725 int loc_PixelToScreenTexCoord;
3726 int loc_ModelToReflectCube;
3727 int loc_ShadowMapMatrix;
3728 int loc_BloomColorSubtract;
3730 r_glsl_permutation_t;
3732 #define SHADERPERMUTATION_HASHSIZE 256
3734 /// information about each possible shader permutation
3735 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3736 /// currently selected permutation
3737 r_glsl_permutation_t *r_glsl_permutation;
3738 /// storage for permutations linked in the hash table
3739 memexpandablearray_t r_glsl_permutationarray;
3741 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3743 //unsigned int hashdepth = 0;
3744 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3745 r_glsl_permutation_t *p;
3746 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3748 if (p->mode == mode && p->permutation == permutation)
3750 //if (hashdepth > 10)
3751 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3756 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3758 p->permutation = permutation;
3759 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3760 r_glsl_permutationhash[mode][hashindex] = p;
3761 //if (hashdepth > 10)
3762 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3766 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3769 if (!filename || !filename[0])
3771 if (!strcmp(filename, "glsl/default.glsl"))
3773 if (!glslshaderstring)
3775 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776 if (glslshaderstring)
3777 Con_DPrintf("Loading shaders from file %s...\n", filename);
3779 glslshaderstring = (char *)builtinshaderstring;
3781 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3782 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3783 return shaderstring;
3785 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3788 if (printfromdisknotice)
3789 Con_DPrintf("from disk %s... ", filename);
3790 return shaderstring;
3792 return shaderstring;
3795 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3798 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3799 int vertstrings_count = 0;
3800 int geomstrings_count = 0;
3801 int fragstrings_count = 0;
3802 char *vertexstring, *geometrystring, *fragmentstring;
3803 const char *vertstrings_list[32+3];
3804 const char *geomstrings_list[32+3];
3805 const char *fragstrings_list[32+3];
3806 char permutationname[256];
3813 permutationname[0] = 0;
3814 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3815 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3816 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3818 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3820 // the first pretext is which type of shader to compile as
3821 // (later these will all be bound together as a program object)
3822 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3826 // the second pretext is the mode (for example a light source)
3827 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3832 // now add all the permutation pretexts
3833 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3835 if (permutation & (1<<i))
3837 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3844 // keep line numbers correct
3845 vertstrings_list[vertstrings_count++] = "\n";
3846 geomstrings_list[geomstrings_count++] = "\n";
3847 fragstrings_list[fragstrings_count++] = "\n";
3851 // now append the shader text itself
3852 vertstrings_list[vertstrings_count++] = vertexstring;
3853 geomstrings_list[geomstrings_count++] = geometrystring;
3854 fragstrings_list[fragstrings_count++] = fragmentstring;
3856 // if any sources were NULL, clear the respective list
3858 vertstrings_count = 0;
3859 if (!geometrystring)
3860 geomstrings_count = 0;
3861 if (!fragmentstring)
3862 fragstrings_count = 0;
3864 // compile the shader program
3865 if (vertstrings_count + geomstrings_count + fragstrings_count)
3866 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3870 qglUseProgramObjectARB(p->program);CHECKGLERROR
3871 // look up all the uniform variable names we care about, so we don't
3872 // have to look them up every time we set them
3874 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3875 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3876 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3877 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3878 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3879 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3880 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3881 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3882 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3883 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3884 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3885 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3886 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3887 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3888 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3889 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3890 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3891 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3892 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3893 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3894 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3895 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3896 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3897 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3898 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3899 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3900 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3901 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3902 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3903 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3904 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3905 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3906 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3907 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3908 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3909 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3910 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3911 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3912 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3913 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3914 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3915 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3916 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3917 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3918 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3919 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3920 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3921 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3922 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3923 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3924 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3925 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3926 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3927 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3928 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3929 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3930 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3931 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3932 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3933 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3934 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3935 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3936 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3937 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3938 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3939 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3940 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3941 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3942 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3943 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3944 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3945 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3946 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3947 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3948 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3949 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3950 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3951 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3952 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3953 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3954 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3955 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3956 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3957 // initialize the samplers to refer to the texture units we use
3958 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3959 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3960 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3961 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3962 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3963 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3964 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3965 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3966 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3967 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3968 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3969 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3970 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3971 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3972 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3973 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3974 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3975 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3976 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3977 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3978 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3979 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3980 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
3981 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3982 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3983 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3984 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3985 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3986 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3987 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3988 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3990 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3993 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3997 Mem_Free(vertexstring);
3999 Mem_Free(geometrystring);
4001 Mem_Free(fragmentstring);
4004 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4006 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4007 if (r_glsl_permutation != perm)
4009 r_glsl_permutation = perm;
4010 if (!r_glsl_permutation->program)
4012 if (!r_glsl_permutation->compiled)
4013 R_GLSL_CompilePermutation(perm, mode, permutation);
4014 if (!r_glsl_permutation->program)
4016 // remove features until we find a valid permutation
4018 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4020 // reduce i more quickly whenever it would not remove any bits
4021 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4022 if (!(permutation & j))
4025 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026 if (!r_glsl_permutation->compiled)
4027 R_GLSL_CompilePermutation(perm, mode, permutation);
4028 if (r_glsl_permutation->program)
4031 if (i >= SHADERPERMUTATION_COUNT)
4033 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4034 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4035 qglUseProgramObjectARB(0);CHECKGLERROR
4036 return; // no bit left to clear, entire mode is broken
4041 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4043 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4044 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4045 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4049 #include <Cg/cgGL.h>
4050 struct r_cg_permutation_s;
4051 typedef struct r_cg_permutation_s
4053 /// hash lookup data
4054 struct r_cg_permutation_s *hashnext;
4056 unsigned int permutation;
4058 /// indicates if we have tried compiling this permutation already
4060 /// 0 if compilation failed
4063 /// locations of detected parameters in programs, or NULL if not found
4064 CGparameter vp_EyePosition;
4065 CGparameter vp_FogPlane;
4066 CGparameter vp_LightDir;
4067 CGparameter vp_LightPosition;
4068 CGparameter vp_ModelToLight;
4069 CGparameter vp_TexMatrix;
4070 CGparameter vp_BackgroundTexMatrix;
4071 CGparameter vp_ModelViewProjectionMatrix;
4072 CGparameter vp_ModelViewMatrix;
4073 CGparameter vp_ShadowMapMatrix;
4075 CGparameter fp_Texture_First;
4076 CGparameter fp_Texture_Second;
4077 CGparameter fp_Texture_GammaRamps;
4078 CGparameter fp_Texture_Normal;
4079 CGparameter fp_Texture_Color;
4080 CGparameter fp_Texture_Gloss;
4081 CGparameter fp_Texture_Glow;
4082 CGparameter fp_Texture_SecondaryNormal;
4083 CGparameter fp_Texture_SecondaryColor;
4084 CGparameter fp_Texture_SecondaryGloss;
4085 CGparameter fp_Texture_SecondaryGlow;
4086 CGparameter fp_Texture_Pants;
4087 CGparameter fp_Texture_Shirt;
4088 CGparameter fp_Texture_FogHeightTexture;
4089 CGparameter fp_Texture_FogMask;
4090 CGparameter fp_Texture_Lightmap;
4091 CGparameter fp_Texture_Deluxemap;
4092 CGparameter fp_Texture_Attenuation;
4093 CGparameter fp_Texture_Cube;
4094 CGparameter fp_Texture_Refraction;
4095 CGparameter fp_Texture_Reflection;
4096 CGparameter fp_Texture_ShadowMapRect;
4097 CGparameter fp_Texture_ShadowMapCube;
4098 CGparameter fp_Texture_ShadowMap2D;
4099 CGparameter fp_Texture_CubeProjection;
4100 CGparameter fp_Texture_ScreenDepth;
4101 CGparameter fp_Texture_ScreenNormalMap;
4102 CGparameter fp_Texture_ScreenDiffuse;
4103 CGparameter fp_Texture_ScreenSpecular;
4104 CGparameter fp_Texture_ReflectMask;
4105 CGparameter fp_Texture_ReflectCube;
4106 CGparameter fp_Alpha;
4107 CGparameter fp_BloomBlur_Parameters;
4108 CGparameter fp_ClientTime;
4109 CGparameter fp_Color_Ambient;
4110 CGparameter fp_Color_Diffuse;
4111 CGparameter fp_Color_Specular;
4112 CGparameter fp_Color_Glow;
4113 CGparameter fp_Color_Pants;
4114 CGparameter fp_Color_Shirt;
4115 CGparameter fp_DeferredColor_Ambient;
4116 CGparameter fp_DeferredColor_Diffuse;
4117 CGparameter fp_DeferredColor_Specular;
4118 CGparameter fp_DeferredMod_Diffuse;
4119 CGparameter fp_DeferredMod_Specular;
4120 CGparameter fp_DistortScaleRefractReflect;
4121 CGparameter fp_EyePosition;
4122 CGparameter fp_FogColor;
4123 CGparameter fp_FogHeightFade;
4124 CGparameter fp_FogPlane;
4125 CGparameter fp_FogPlaneViewDist;
4126 CGparameter fp_FogRangeRecip;
4127 CGparameter fp_LightColor;
4128 CGparameter fp_LightDir;
4129 CGparameter fp_LightPosition;
4130 CGparameter fp_OffsetMapping_Scale;
4131 CGparameter fp_PixelSize;
4132 CGparameter fp_ReflectColor;
4133 CGparameter fp_ReflectFactor;
4134 CGparameter fp_ReflectOffset;
4135 CGparameter fp_RefractColor;
4136 CGparameter fp_Saturation;
4137 CGparameter fp_ScreenCenterRefractReflect;
4138 CGparameter fp_ScreenScaleRefractReflect;
4139 CGparameter fp_ScreenToDepth;
4140 CGparameter fp_ShadowMap_Parameters;
4141 CGparameter fp_ShadowMap_TextureScale;
4142 CGparameter fp_SpecularPower;
4143 CGparameter fp_UserVec1;
4144 CGparameter fp_UserVec2;
4145 CGparameter fp_UserVec3;
4146 CGparameter fp_UserVec4;
4147 CGparameter fp_ViewTintColor;
4148 CGparameter fp_ViewToLight;
4149 CGparameter fp_PixelToScreenTexCoord;
4150 CGparameter fp_ModelToReflectCube;
4151 CGparameter fp_BloomColorSubtract;
4155 /// information about each possible shader permutation
4156 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4157 /// currently selected permutation
4158 r_cg_permutation_t *r_cg_permutation;
4159 /// storage for permutations linked in the hash table
4160 memexpandablearray_t r_cg_permutationarray;
4162 #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));}}
4164 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4166 //unsigned int hashdepth = 0;
4167 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4168 r_cg_permutation_t *p;
4169 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4171 if (p->mode == mode && p->permutation == permutation)
4173 //if (hashdepth > 10)
4174 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4179 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4181 p->permutation = permutation;
4182 p->hashnext = r_cg_permutationhash[mode][hashindex];
4183 r_cg_permutationhash[mode][hashindex] = p;
4184 //if (hashdepth > 10)
4185 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4189 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4192 if (!filename || !filename[0])
4194 if (!strcmp(filename, "cg/default.cg"))
4196 if (!cgshaderstring)
4198 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4200 Con_DPrintf("Loading shaders from file %s...\n", filename);
4202 cgshaderstring = (char *)builtincgshaderstring;
4204 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4205 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4206 return shaderstring;
4208 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4211 if (printfromdisknotice)
4212 Con_DPrintf("from disk %s... ", filename);
4213 return shaderstring;
4215 return shaderstring;
4218 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4220 // TODO: load or create .fp and .vp shader files
4223 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4226 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4227 int vertstrings_count = 0, vertstring_length = 0;
4228 int geomstrings_count = 0, geomstring_length = 0;
4229 int fragstrings_count = 0, fragstring_length = 0;
4231 char *vertexstring, *geometrystring, *fragmentstring;
4232 char *vertstring, *geomstring, *fragstring;
4233 const char *vertstrings_list[32+3];
4234 const char *geomstrings_list[32+3];
4235 const char *fragstrings_list[32+3];
4236 char permutationname[256];
4237 char cachename[256];
4238 CGprofile vertexProfile;
4239 CGprofile fragmentProfile;
4247 permutationname[0] = 0;
4249 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4250 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4251 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4253 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4254 strlcat(cachename, "cg/", sizeof(cachename));
4256 // the first pretext is which type of shader to compile as
4257 // (later these will all be bound together as a program object)
4258 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4259 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4260 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4262 // the second pretext is the mode (for example a light source)
4263 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4264 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4265 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4266 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4267 strlcat(cachename, modeinfo->name, sizeof(cachename));
4269 // now add all the permutation pretexts
4270 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4272 if (permutation & (1<<i))
4274 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4275 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4276 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4277 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4278 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4282 // keep line numbers correct
4283 vertstrings_list[vertstrings_count++] = "\n";
4284 geomstrings_list[geomstrings_count++] = "\n";
4285 fragstrings_list[fragstrings_count++] = "\n";
4289 // replace spaces in the cachename with _ characters
4290 for (i = 0;cachename[i];i++)
4291 if (cachename[i] == ' ')
4294 // now append the shader text itself
4295 vertstrings_list[vertstrings_count++] = vertexstring;
4296 geomstrings_list[geomstrings_count++] = geometrystring;
4297 fragstrings_list[fragstrings_count++] = fragmentstring;
4299 // if any sources were NULL, clear the respective list
4301 vertstrings_count = 0;
4302 if (!geometrystring)
4303 geomstrings_count = 0;
4304 if (!fragmentstring)
4305 fragstrings_count = 0;
4307 vertstring_length = 0;
4308 for (i = 0;i < vertstrings_count;i++)
4309 vertstring_length += strlen(vertstrings_list[i]);
4310 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4311 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4312 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4314 geomstring_length = 0;
4315 for (i = 0;i < geomstrings_count;i++)
4316 geomstring_length += strlen(geomstrings_list[i]);
4317 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4318 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4319 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4321 fragstring_length = 0;
4322 for (i = 0;i < fragstrings_count;i++)
4323 fragstring_length += strlen(fragstrings_list[i]);
4324 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4325 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4326 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4330 //vertexProfile = CG_PROFILE_ARBVP1;
4331 //fragmentProfile = CG_PROFILE_ARBFP1;
4332 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4333 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4334 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4335 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4336 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4339 // try to load the cached shader, or generate one
4340 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4342 // if caching failed, do a dynamic compile for now
4344 if (vertstring[0] && !p->vprogram)
4345 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4347 if (fragstring[0] && !p->fprogram)
4348 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4351 // look up all the uniform variable names we care about, so we don't
4352 // have to look them up every time we set them
4356 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4357 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4358 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4359 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4360 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4361 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4362 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4363 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4364 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4365 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4366 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4367 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4373 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4374 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4375 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4376 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4377 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4378 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4379 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4380 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4381 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4382 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4383 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4384 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4385 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4386 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4387 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4388 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4389 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4390 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4391 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4392 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4393 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4394 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4395 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4396 p->fp_Texture_ShadowMapRect = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4397 p->fp_Texture_ShadowMapCube = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4398 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4399 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4400 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4401 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4402 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4403 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4404 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4405 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4406 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4407 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4408 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4409 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4410 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4411 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4412 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4413 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4414 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4415 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4416 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4417 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4418 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4419 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4420 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4421 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4422 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4423 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4424 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4425 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4426 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4427 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4428 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4429 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4430 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4431 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4432 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4433 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4434 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4435 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4436 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4437 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4438 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4439 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4440 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4441 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4442 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4443 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4444 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4445 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4446 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4447 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4448 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4449 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4450 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4451 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4455 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4456 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4458 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4462 Mem_Free(vertstring);
4464 Mem_Free(geomstring);
4466 Mem_Free(fragstring);
4468 Mem_Free(vertexstring);
4470 Mem_Free(geometrystring);
4472 Mem_Free(fragmentstring);
4475 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4477 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4480 if (r_cg_permutation != perm)
4482 r_cg_permutation = perm;
4483 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4485 if (!r_cg_permutation->compiled)
4486 R_CG_CompilePermutation(perm, mode, permutation);
4487 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4489 // remove features until we find a valid permutation
4491 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4493 // reduce i more quickly whenever it would not remove any bits
4494 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4495 if (!(permutation & j))
4498 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4499 if (!r_cg_permutation->compiled)
4500 R_CG_CompilePermutation(perm, mode, permutation);
4501 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4504 if (i >= SHADERPERMUTATION_COUNT)
4506 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4507 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4508 return; // no bit left to clear, entire mode is broken
4514 if (r_cg_permutation->vprogram)
4516 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4517 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4518 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4522 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4523 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4525 if (r_cg_permutation->fprogram)
4527 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4528 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4529 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4533 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4534 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4538 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4539 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4540 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4543 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4545 cgGLSetTextureParameter(param, R_GetTexture(tex));
4546 cgGLEnableTextureParameter(param);
4554 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4555 extern D3DCAPS9 vid_d3d9caps;
4558 struct r_hlsl_permutation_s;
4559 typedef struct r_hlsl_permutation_s
4561 /// hash lookup data
4562 struct r_hlsl_permutation_s *hashnext;
4564 unsigned int permutation;
4566 /// indicates if we have tried compiling this permutation already
4568 /// NULL if compilation failed
4569 IDirect3DVertexShader9 *vertexshader;
4570 IDirect3DPixelShader9 *pixelshader;
4572 r_hlsl_permutation_t;
4574 typedef enum D3DVSREGISTER_e
4576 D3DVSREGISTER_TexMatrix = 0, // float4x4
4577 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4578 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4579 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4580 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4581 D3DVSREGISTER_ModelToLight = 20, // float4x4
4582 D3DVSREGISTER_EyePosition = 24,
4583 D3DVSREGISTER_FogPlane = 25,
4584 D3DVSREGISTER_LightDir = 26,
4585 D3DVSREGISTER_LightPosition = 27,
4589 typedef enum D3DPSREGISTER_e
4591 D3DPSREGISTER_Alpha = 0,
4592 D3DPSREGISTER_BloomBlur_Parameters = 1,
4593 D3DPSREGISTER_ClientTime = 2,
4594 D3DPSREGISTER_Color_Ambient = 3,
4595 D3DPSREGISTER_Color_Diffuse = 4,
4596 D3DPSREGISTER_Color_Specular = 5,
4597 D3DPSREGISTER_Color_Glow = 6,
4598 D3DPSREGISTER_Color_Pants = 7,
4599 D3DPSREGISTER_Color_Shirt = 8,
4600 D3DPSREGISTER_DeferredColor_Ambient = 9,
4601 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4602 D3DPSREGISTER_DeferredColor_Specular = 11,
4603 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4604 D3DPSREGISTER_DeferredMod_Specular = 13,
4605 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4606 D3DPSREGISTER_EyePosition = 15, // unused
4607 D3DPSREGISTER_FogColor = 16,
4608 D3DPSREGISTER_FogHeightFade = 17,
4609 D3DPSREGISTER_FogPlane = 18,
4610 D3DPSREGISTER_FogPlaneViewDist = 19,
4611 D3DPSREGISTER_FogRangeRecip = 20,
4612 D3DPSREGISTER_LightColor = 21,
4613 D3DPSREGISTER_LightDir = 22, // unused
4614 D3DPSREGISTER_LightPosition = 23,
4615 D3DPSREGISTER_OffsetMapping_Scale = 24,
4616 D3DPSREGISTER_PixelSize = 25,
4617 D3DPSREGISTER_ReflectColor = 26,
4618 D3DPSREGISTER_ReflectFactor = 27,
4619 D3DPSREGISTER_ReflectOffset = 28,
4620 D3DPSREGISTER_RefractColor = 29,
4621 D3DPSREGISTER_Saturation = 30,
4622 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4623 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4624 D3DPSREGISTER_ScreenToDepth = 33,
4625 D3DPSREGISTER_ShadowMap_Parameters = 34,
4626 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4627 D3DPSREGISTER_SpecularPower = 36,
4628 D3DPSREGISTER_UserVec1 = 37,
4629 D3DPSREGISTER_UserVec2 = 38,
4630 D3DPSREGISTER_UserVec3 = 39,
4631 D3DPSREGISTER_UserVec4 = 40,
4632 D3DPSREGISTER_ViewTintColor = 41,
4633 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4634 D3DPSREGISTER_BloomColorSubtract = 43,
4635 D3DPSREGISTER_ViewToLight = 44, // float4x4
4636 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4641 /// information about each possible shader permutation
4642 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4643 /// currently selected permutation
4644 r_hlsl_permutation_t *r_hlsl_permutation;
4645 /// storage for permutations linked in the hash table
4646 memexpandablearray_t r_hlsl_permutationarray;
4648 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4650 //unsigned int hashdepth = 0;
4651 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4652 r_hlsl_permutation_t *p;
4653 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4655 if (p->mode == mode && p->permutation == permutation)
4657 //if (hashdepth > 10)
4658 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4663 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4665 p->permutation = permutation;
4666 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4667 r_hlsl_permutationhash[mode][hashindex] = p;
4668 //if (hashdepth > 10)
4669 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4673 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4676 if (!filename || !filename[0])
4678 if (!strcmp(filename, "hlsl/default.hlsl"))
4680 if (!hlslshaderstring)
4682 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4683 if (hlslshaderstring)
4684 Con_DPrintf("Loading shaders from file %s...\n", filename);
4686 hlslshaderstring = (char *)builtincgshaderstring;
4688 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4689 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4690 return shaderstring;
4692 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4695 if (printfromdisknotice)
4696 Con_DPrintf("from disk %s... ", filename);
4697 return shaderstring;
4699 return shaderstring;
4703 //#include <d3dx9shader.h>
4704 //#include <d3dx9mesh.h>
4706 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4708 DWORD *vsbin = NULL;
4709 DWORD *psbin = NULL;
4710 fs_offset_t vsbinsize;
4711 fs_offset_t psbinsize;
4712 // IDirect3DVertexShader9 *vs = NULL;
4713 // IDirect3DPixelShader9 *ps = NULL;
4714 ID3DXBuffer *vslog = NULL;
4715 ID3DXBuffer *vsbuffer = NULL;
4716 ID3DXConstantTable *vsconstanttable = NULL;
4717 ID3DXBuffer *pslog = NULL;
4718 ID3DXBuffer *psbuffer = NULL;
4719 ID3DXConstantTable *psconstanttable = NULL;
4722 char temp[MAX_INPUTLINE];
4723 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4724 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4725 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4726 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4727 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4728 if ((!vsbin && vertstring) || (!psbin && fragstring))
4730 const char* dllnames_d3dx9 [] =
4754 dllhandle_t d3dx9_dll = NULL;
4755 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4756 // HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4757 dllfunction_t d3dx9_dllfuncs[] =
4759 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4760 // {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4763 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4765 DWORD shaderflags = 0;
4766 // shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4767 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4768 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4769 if (vertstring && vertstring[0])
4771 // FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4772 // vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4773 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4776 vsbinsize = vsbuffer->GetBufferSize();
4777 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4778 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4779 vsbuffer->Release();
4783 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4784 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4788 if (fragstring && fragstring[0])
4790 // FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4791 // psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4792 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4795 psbinsize = psbuffer->GetBufferSize();
4796 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4797 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4798 psbuffer->Release();
4802 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4803 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4807 Sys_UnloadLibrary(&d3dx9_dll);
4810 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4814 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4815 if (FAILED(vsresult))
4816 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4820 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4821 if (FAILED(psresult))
4822 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4824 // free the shader data
4825 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4826 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4829 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4832 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4833 int vertstrings_count = 0, vertstring_length = 0;
4834 int geomstrings_count = 0, geomstring_length = 0;
4835 int fragstrings_count = 0, fragstring_length = 0;
4837 char *vertexstring, *geometrystring, *fragmentstring;
4838 char *vertstring, *geomstring, *fragstring;
4839 const char *vertstrings_list[32+3];
4840 const char *geomstrings_list[32+3];
4841 const char *fragstrings_list[32+3];
4842 char permutationname[256];
4843 char cachename[256];
4848 p->vertexshader = NULL;
4849 p->pixelshader = NULL;
4851 permutationname[0] = 0;
4853 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4854 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4855 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4857 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4858 strlcat(cachename, "hlsl/", sizeof(cachename));
4860 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4861 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4862 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4863 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4865 // the first pretext is which type of shader to compile as
4866 // (later these will all be bound together as a program object)
4867 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4868 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4869 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4871 // the second pretext is the mode (for example a light source)
4872 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4873 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4874 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4875 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4876 strlcat(cachename, modeinfo->name, sizeof(cachename));
4878 // now add all the permutation pretexts
4879 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4881 if (permutation & (1<<i))
4883 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4884 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4885 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4886 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4887 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4891 // keep line numbers correct
4892 vertstrings_list[vertstrings_count++] = "\n";
4893 geomstrings_list[geomstrings_count++] = "\n";
4894 fragstrings_list[fragstrings_count++] = "\n";
4898 // replace spaces in the cachename with _ characters
4899 for (i = 0;cachename[i];i++)
4900 if (cachename[i] == ' ')
4903 // now append the shader text itself
4904 vertstrings_list[vertstrings_count++] = vertexstring;
4905 geomstrings_list[geomstrings_count++] = geometrystring;
4906 fragstrings_list[fragstrings_count++] = fragmentstring;
4908 // if any sources were NULL, clear the respective list
4910 vertstrings_count = 0;
4911 if (!geometrystring)
4912 geomstrings_count = 0;
4913 if (!fragmentstring)
4914 fragstrings_count = 0;
4916 vertstring_length = 0;
4917 for (i = 0;i < vertstrings_count;i++)
4918 vertstring_length += strlen(vertstrings_list[i]);
4919 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4920 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4921 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4923 geomstring_length = 0;
4924 for (i = 0;i < geomstrings_count;i++)
4925 geomstring_length += strlen(geomstrings_list[i]);
4926 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4927 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4928 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4930 fragstring_length = 0;
4931 for (i = 0;i < fragstrings_count;i++)
4932 fragstring_length += strlen(fragstrings_list[i]);
4933 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4934 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4935 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4937 // try to load the cached shader, or generate one
4938 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4940 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4941 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4943 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4947 Mem_Free(vertstring);
4949 Mem_Free(geomstring);
4951 Mem_Free(fragstring);
4953 Mem_Free(vertexstring);
4955 Mem_Free(geometrystring);
4957 Mem_Free(fragmentstring);
4960 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4961 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4962 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);}
4963 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);}
4964 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);}
4965 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);}
4967 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4968 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4969 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);}
4970 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);}
4971 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);}
4972 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);}
4974 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4976 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4977 if (r_hlsl_permutation != perm)
4979 r_hlsl_permutation = perm;
4980 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4982 if (!r_hlsl_permutation->compiled)
4983 R_HLSL_CompilePermutation(perm, mode, permutation);
4984 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4986 // remove features until we find a valid permutation
4988 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4990 // reduce i more quickly whenever it would not remove any bits
4991 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4992 if (!(permutation & j))
4995 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4996 if (!r_hlsl_permutation->compiled)
4997 R_HLSL_CompilePermutation(perm, mode, permutation);
4998 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
5001 if (i >= SHADERPERMUTATION_COUNT)
5003 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5004 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5005 return; // no bit left to clear, entire mode is broken
5009 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5010 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5012 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5013 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5014 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5018 void R_GLSL_Restart_f(void)
5020 unsigned int i, limit;
5021 if (glslshaderstring && glslshaderstring != builtinshaderstring)
5022 Mem_Free(glslshaderstring);
5023 glslshaderstring = NULL;
5024 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5025 Mem_Free(cgshaderstring);
5026 cgshaderstring = NULL;
5027 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5028 Mem_Free(hlslshaderstring);
5029 hlslshaderstring = NULL;
5030 switch(vid.renderpath)
5032 case RENDERPATH_D3D9:
5035 r_hlsl_permutation_t *p;
5036 r_hlsl_permutation = NULL;
5037 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5038 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5039 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5040 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5041 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5042 for (i = 0;i < limit;i++)
5044 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5046 if (p->vertexshader)
5047 IDirect3DVertexShader9_Release(p->vertexshader);
5049 IDirect3DPixelShader9_Release(p->pixelshader);
5050 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5053 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5057 case RENDERPATH_D3D10:
5058 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5060 case RENDERPATH_D3D11:
5061 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5063 case RENDERPATH_GL20:
5065 r_glsl_permutation_t *p;
5066 r_glsl_permutation = NULL;
5067 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5068 for (i = 0;i < limit;i++)
5070 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5072 GL_Backend_FreeProgram(p->program);
5073 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5076 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5079 case RENDERPATH_CGGL:
5082 r_cg_permutation_t *p;
5083 r_cg_permutation = NULL;
5084 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5085 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5086 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5087 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5088 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5089 for (i = 0;i < limit;i++)
5091 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5094 cgDestroyProgram(p->vprogram);
5096 cgDestroyProgram(p->fprogram);
5097 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5100 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5104 case RENDERPATH_GL13:
5105 case RENDERPATH_GL11:
5110 void R_GLSL_DumpShader_f(void)
5115 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5118 FS_Print(file, "/* The engine may define the following macros:\n");
5119 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5120 for (i = 0;i < SHADERMODE_COUNT;i++)
5121 FS_Print(file, glslshadermodeinfo[i].pretext);
5122 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5123 FS_Print(file, shaderpermutationinfo[i].pretext);
5124 FS_Print(file, "*/\n");
5125 FS_Print(file, builtinshaderstring);
5127 Con_Printf("glsl/default.glsl written\n");
5130 Con_Printf("failed to write to glsl/default.glsl\n");
5133 file = FS_OpenRealFile("cg/default.cg", "w", false);
5136 FS_Print(file, "/* The engine may define the following macros:\n");
5137 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5138 for (i = 0;i < SHADERMODE_COUNT;i++)
5139 FS_Print(file, cgshadermodeinfo[i].pretext);
5140 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5141 FS_Print(file, shaderpermutationinfo[i].pretext);
5142 FS_Print(file, "*/\n");
5143 FS_Print(file, builtincgshaderstring);
5145 Con_Printf("cg/default.cg written\n");
5148 Con_Printf("failed to write to cg/default.cg\n");
5152 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5155 FS_Print(file, "/* The engine may define the following macros:\n");
5156 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5157 for (i = 0;i < SHADERMODE_COUNT;i++)
5158 FS_Print(file, hlslshadermodeinfo[i].pretext);
5159 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5160 FS_Print(file, shaderpermutationinfo[i].pretext);
5161 FS_Print(file, "*/\n");
5162 FS_Print(file, builtincgshaderstring);
5164 Con_Printf("hlsl/default.hlsl written\n");
5167 Con_Printf("failed to write to hlsl/default.hlsl\n");
5171 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5174 texturemode = GL_MODULATE;
5175 switch (vid.renderpath)
5177 case RENDERPATH_D3D9:
5179 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))));
5180 R_Mesh_TexBind(GL20TU_FIRST , first );
5181 R_Mesh_TexBind(GL20TU_SECOND, second);
5184 case RENDERPATH_D3D10:
5185 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5187 case RENDERPATH_D3D11:
5188 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5190 case RENDERPATH_GL20:
5191 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))));
5192 R_Mesh_TexBind(GL20TU_FIRST , first );
5193 R_Mesh_TexBind(GL20TU_SECOND, second);
5195 case RENDERPATH_CGGL:
5198 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))));
5199 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5200 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5203 case RENDERPATH_GL13:
5204 R_Mesh_TexBind(0, first );
5205 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5206 R_Mesh_TexBind(1, second);
5208 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5210 case RENDERPATH_GL11:
5211 R_Mesh_TexBind(0, first );
5216 void R_SetupShader_DepthOrShadow(void)
5218 switch (vid.renderpath)
5220 case RENDERPATH_D3D9:
5222 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5225 case RENDERPATH_D3D10:
5226 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5228 case RENDERPATH_D3D11:
5229 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5231 case RENDERPATH_GL20:
5232 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5234 case RENDERPATH_CGGL:
5236 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5239 case RENDERPATH_GL13:
5240 R_Mesh_TexBind(0, 0);
5241 R_Mesh_TexBind(1, 0);
5243 case RENDERPATH_GL11:
5244 R_Mesh_TexBind(0, 0);
5249 void R_SetupShader_ShowDepth(void)
5251 switch (vid.renderpath)
5253 case RENDERPATH_D3D9:
5255 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5258 case RENDERPATH_D3D10:
5259 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5261 case RENDERPATH_D3D11:
5262 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5264 case RENDERPATH_GL20:
5265 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5267 case RENDERPATH_CGGL:
5269 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5272 case RENDERPATH_GL13:
5274 case RENDERPATH_GL11:
5279 extern qboolean r_shadow_usingdeferredprepass;
5280 extern cvar_t r_shadow_deferred_8bitrange;
5281 extern rtexture_t *r_shadow_attenuationgradienttexture;
5282 extern rtexture_t *r_shadow_attenuation2dtexture;
5283 extern rtexture_t *r_shadow_attenuation3dtexture;
5284 extern qboolean r_shadow_usingshadowmaprect;
5285 extern qboolean r_shadow_usingshadowmapcube;
5286 extern qboolean r_shadow_usingshadowmap2d;
5287 extern qboolean r_shadow_usingshadowmaportho;
5288 extern float r_shadow_shadowmap_texturescale[2];
5289 extern float r_shadow_shadowmap_parameters[4];
5290 extern qboolean r_shadow_shadowmapvsdct;
5291 extern qboolean r_shadow_shadowmapsampler;
5292 extern int r_shadow_shadowmappcf;
5293 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5294 extern rtexture_t *r_shadow_shadowmap2dtexture;
5295 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5296 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5297 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5298 extern matrix4x4_t r_shadow_shadowmapmatrix;
5299 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5300 extern int r_shadow_prepass_width;
5301 extern int r_shadow_prepass_height;
5302 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5303 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5304 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5305 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5306 extern cvar_t gl_mesh_separatearrays;
5307 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5309 // a blendfunc allows colormod if:
5310 // a) it can never keep the destination pixel invariant, or
5311 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5312 // this is to prevent unintended side effects from colormod
5315 // IF there is a (s, sa) for which for all (d, da),
5316 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5317 // THEN, for this (s, sa) and all (colormod, d, da):
5318 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5319 // OBVIOUSLY, this means that
5320 // s*colormod * src(s*colormod, d, sa, da) = 0
5321 // dst(s*colormod, d, sa, da) = 1
5323 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5325 // main condition to leave dst color invariant:
5326 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5328 // s * 0 + d * dst(s, d, sa, da) == d
5329 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5330 // => colormod is a problem for GL_SRC_COLOR only
5332 // s + d * dst(s, d, sa, da) == d
5334 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5335 // => colormod is never problematic for these
5336 // src == GL_SRC_COLOR:
5337 // s*s + d * dst(s, d, sa, da) == d
5339 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5340 // => colormod is never problematic for these
5341 // src == GL_ONE_MINUS_SRC_COLOR:
5342 // s*(1-s) + d * dst(s, d, sa, da) == d
5343 // => s == 0 or s == 1
5344 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5345 // => colormod is a problem for GL_SRC_COLOR only
5346 // src == GL_DST_COLOR
5347 // s*d + d * dst(s, d, sa, da) == d
5349 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5350 // => colormod is always a problem
5353 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5354 // => colormod is never problematic for these
5355 // => BUT, we do not know s! We must assume it is problematic
5356 // then... except in GL_ONE case, where we know all invariant
5358 // src == GL_ONE_MINUS_DST_COLOR
5359 // s*(1-d) + d * dst(s, d, sa, da) == d
5360 // => s == 0 (1-d is impossible to handle for our desired result)
5361 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5362 // => colormod is never problematic for these
5363 // src == GL_SRC_ALPHA
5364 // s*sa + d * dst(s, d, sa, da) == d
5365 // => s == 0, or sa == 0
5366 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5367 // => colormod breaks in the case GL_SRC_COLOR only
5368 // src == GL_ONE_MINUS_SRC_ALPHA
5369 // s*(1-sa) + d * dst(s, d, sa, da) == d
5370 // => s == 0, or sa == 1
5371 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5372 // => colormod breaks in the case GL_SRC_COLOR only
5373 // src == GL_DST_ALPHA
5374 // s*da + d * dst(s, d, sa, da) == d
5376 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5377 // => colormod is never problematic for these
5382 case GL_ONE_MINUS_SRC_COLOR:
5384 case GL_ONE_MINUS_SRC_ALPHA:
5385 if(dst == GL_SRC_COLOR)
5390 case GL_ONE_MINUS_DST_COLOR:
5392 case GL_ONE_MINUS_DST_ALPHA:
5402 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)
5404 // select a permutation of the lighting shader appropriate to this
5405 // combination of texture, entity, light source, and fogging, only use the
5406 // minimum features necessary to avoid wasting rendering time in the
5407 // fragment shader on features that are not being used
5408 unsigned int permutation = 0;
5409 unsigned int mode = 0;
5410 qboolean allow_colormod;
5411 static float dummy_colormod[3] = {1, 1, 1};
5412 float *colormod = rsurface.colormod;
5414 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5415 if (rsurfacepass == RSURFPASS_BACKGROUND)
5417 // distorted background
5418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5419 mode = SHADERMODE_WATER;
5420 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5421 mode = SHADERMODE_REFRACTION;
5424 mode = SHADERMODE_GENERIC;
5425 permutation |= SHADERPERMUTATION_DIFFUSE;
5427 GL_AlphaTest(false);
5428 GL_BlendFunc(GL_ONE, GL_ZERO);
5429 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5431 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5433 if (r_glsl_offsetmapping.integer)
5435 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5436 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5437 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5438 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5439 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5441 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5442 if (r_glsl_offsetmapping_reliefmapping.integer)
5443 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5446 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5447 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5449 permutation |= SHADERPERMUTATION_ALPHAKILL;
5450 // normalmap (deferred prepass), may use alpha test on diffuse
5451 mode = SHADERMODE_DEFERREDGEOMETRY;
5452 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5453 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5454 GL_AlphaTest(false);
5455 GL_BlendFunc(GL_ONE, GL_ZERO);
5456 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5458 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5460 if (r_glsl_offsetmapping.integer)
5462 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5463 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5464 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5465 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5466 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5468 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5469 if (r_glsl_offsetmapping_reliefmapping.integer)
5470 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5473 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5474 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5476 mode = SHADERMODE_LIGHTSOURCE;
5477 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5478 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5479 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5480 permutation |= SHADERPERMUTATION_CUBEFILTER;
5481 if (diffusescale > 0)
5482 permutation |= SHADERPERMUTATION_DIFFUSE;
5483 if (specularscale > 0)
5485 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5486 if (r_shadow_glossexact.integer)
5487 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5489 if (r_refdef.fogenabled)
5490 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5491 if (rsurface.texture->colormapping)
5492 permutation |= SHADERPERMUTATION_COLORMAPPING;
5493 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5495 if (r_shadow_usingshadowmaprect)
5496 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5497 if (r_shadow_usingshadowmap2d)
5498 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5499 if (r_shadow_usingshadowmapcube)
5500 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5501 else if(r_shadow_shadowmapvsdct)
5502 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5504 if (r_shadow_shadowmapsampler)
5505 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5506 if (r_shadow_shadowmappcf > 1)
5507 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5508 else if (r_shadow_shadowmappcf)
5509 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5511 if (rsurface.texture->reflectmasktexture)
5512 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5513 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5514 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5515 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5517 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5519 if (r_glsl_offsetmapping.integer)
5521 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5522 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5523 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5524 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5525 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5527 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5528 if (r_glsl_offsetmapping_reliefmapping.integer)
5529 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5532 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5533 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5534 // unshaded geometry (fullbright or ambient model lighting)
5535 mode = SHADERMODE_FLATCOLOR;
5536 ambientscale = diffusescale = specularscale = 0;
5537 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5538 permutation |= SHADERPERMUTATION_GLOW;
5539 if (r_refdef.fogenabled)
5540 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5541 if (rsurface.texture->colormapping)
5542 permutation |= SHADERPERMUTATION_COLORMAPPING;
5543 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5545 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5546 if (r_shadow_usingshadowmaprect)
5547 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5548 if (r_shadow_usingshadowmap2d)
5549 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5551 if (r_shadow_shadowmapsampler)
5552 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5553 if (r_shadow_shadowmappcf > 1)
5554 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5555 else if (r_shadow_shadowmappcf)
5556 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5558 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5559 permutation |= SHADERPERMUTATION_REFLECTION;
5560 if (rsurface.texture->reflectmasktexture)
5561 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5562 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5563 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5564 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5566 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5568 if (r_glsl_offsetmapping.integer)
5570 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5571 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5572 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5573 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5574 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5576 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5577 if (r_glsl_offsetmapping_reliefmapping.integer)
5578 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5581 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5582 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5583 // directional model lighting
5584 mode = SHADERMODE_LIGHTDIRECTION;
5585 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5586 permutation |= SHADERPERMUTATION_GLOW;
5587 permutation |= SHADERPERMUTATION_DIFFUSE;
5588 if (specularscale > 0)
5590 permutation |= SHADERPERMUTATION_SPECULAR;
5591 if (r_shadow_glossexact.integer)
5592 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5594 if (r_refdef.fogenabled)
5595 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5596 if (rsurface.texture->colormapping)
5597 permutation |= SHADERPERMUTATION_COLORMAPPING;
5598 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5600 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5601 if (r_shadow_usingshadowmaprect)
5602 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5603 if (r_shadow_usingshadowmap2d)
5604 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5606 if (r_shadow_shadowmapsampler)
5607 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5608 if (r_shadow_shadowmappcf > 1)
5609 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5610 else if (r_shadow_shadowmappcf)
5611 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5613 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5614 permutation |= SHADERPERMUTATION_REFLECTION;
5615 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5616 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5617 if (rsurface.texture->reflectmasktexture)
5618 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5619 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5620 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5621 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5623 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5625 if (r_glsl_offsetmapping.integer)
5627 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5628 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5629 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5630 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5631 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5633 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5634 if (r_glsl_offsetmapping_reliefmapping.integer)
5635 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5638 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5639 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5640 // ambient model lighting
5641 mode = SHADERMODE_LIGHTDIRECTION;
5642 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5643 permutation |= SHADERPERMUTATION_GLOW;
5644 if (r_refdef.fogenabled)
5645 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5646 if (rsurface.texture->colormapping)
5647 permutation |= SHADERPERMUTATION_COLORMAPPING;
5648 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5650 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5651 if (r_shadow_usingshadowmaprect)
5652 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5653 if (r_shadow_usingshadowmap2d)
5654 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5656 if (r_shadow_shadowmapsampler)
5657 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5658 if (r_shadow_shadowmappcf > 1)
5659 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5660 else if (r_shadow_shadowmappcf)
5661 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5663 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5664 permutation |= SHADERPERMUTATION_REFLECTION;
5665 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5666 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5667 if (rsurface.texture->reflectmasktexture)
5668 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5669 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5670 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5671 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5675 if (r_glsl_offsetmapping.integer)
5677 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5678 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5679 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5680 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5681 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5683 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5684 if (r_glsl_offsetmapping_reliefmapping.integer)
5685 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5689 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5691 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5692 permutation |= SHADERPERMUTATION_GLOW;
5693 if (r_refdef.fogenabled)
5694 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5695 if (rsurface.texture->colormapping)
5696 permutation |= SHADERPERMUTATION_COLORMAPPING;
5697 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5699 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5700 if (r_shadow_usingshadowmaprect)
5701 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5702 if (r_shadow_usingshadowmap2d)
5703 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5705 if (r_shadow_shadowmapsampler)
5706 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5707 if (r_shadow_shadowmappcf > 1)
5708 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5709 else if (r_shadow_shadowmappcf)
5710 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5712 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5713 permutation |= SHADERPERMUTATION_REFLECTION;
5714 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5715 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5716 if (rsurface.texture->reflectmasktexture)
5717 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5718 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5720 // deluxemapping (light direction texture)
5721 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5722 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5724 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5725 permutation |= SHADERPERMUTATION_DIFFUSE;
5726 if (specularscale > 0)
5728 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5729 if (r_shadow_glossexact.integer)
5730 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5733 else if (r_glsl_deluxemapping.integer >= 2)
5735 // fake deluxemapping (uniform light direction in tangentspace)
5736 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5737 permutation |= SHADERPERMUTATION_DIFFUSE;
5738 if (specularscale > 0)
5740 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5741 if (r_shadow_glossexact.integer)
5742 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5745 else if (rsurface.uselightmaptexture)
5747 // ordinary lightmapping (q1bsp, q3bsp)
5748 mode = SHADERMODE_LIGHTMAP;
5752 // ordinary vertex coloring (q3bsp)
5753 mode = SHADERMODE_VERTEXCOLOR;
5755 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5756 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5757 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5760 colormod = dummy_colormod;
5761 switch(vid.renderpath)
5763 case RENDERPATH_D3D9:
5765 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);
5766 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5767 R_SetupShader_SetPermutationHLSL(mode, permutation);
5768 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5769 if (mode == SHADERMODE_LIGHTSOURCE)
5771 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5772 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5776 if (mode == SHADERMODE_LIGHTDIRECTION)
5778 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5781 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5782 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5783 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5784 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5785 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5787 if (mode == SHADERMODE_LIGHTSOURCE)
5789 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5790 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5791 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5792 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5793 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5795 // additive passes are only darkened by fog, not tinted
5796 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5797 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5801 if (mode == SHADERMODE_FLATCOLOR)
5803 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5805 else if (mode == SHADERMODE_LIGHTDIRECTION)
5807 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]);
5808 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5809 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);
5810 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);
5811 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5812 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5813 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5817 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5818 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5819 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);
5820 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);
5821 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5823 // additive passes are only darkened by fog, not tinted
5824 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5825 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5827 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5828 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);
5829 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5830 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5831 hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5832 hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5833 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5834 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5835 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5837 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5838 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5839 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5840 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5841 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5842 if (rsurface.texture->pantstexture)
5843 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5845 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5846 if (rsurface.texture->shirttexture)
5847 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5849 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5850 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5851 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5852 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5853 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5854 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5855 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5856 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5858 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5859 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5860 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5861 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5862 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5863 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5864 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5865 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5866 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5867 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5868 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5869 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5870 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5871 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5872 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5873 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5874 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5875 if (rsurfacepass == RSURFPASS_BACKGROUND)
5877 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5878 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5879 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5883 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5885 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5886 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5887 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5888 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5889 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5891 R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5892 if (rsurface.rtlight)
5894 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5895 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5900 case RENDERPATH_D3D10:
5901 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5903 case RENDERPATH_D3D11:
5904 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5906 case RENDERPATH_GL20:
5907 if (gl_mesh_separatearrays.integer)
5909 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);
5910 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5911 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5912 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5913 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5914 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5915 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5916 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5920 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);
5921 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5923 R_SetupShader_SetPermutationGLSL(mode, permutation);
5924 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5925 if (mode == SHADERMODE_LIGHTSOURCE)
5927 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5928 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5929 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5930 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5931 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5932 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);
5934 // additive passes are only darkened by fog, not tinted
5935 if (r_glsl_permutation->loc_FogColor >= 0)
5936 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5937 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5941 if (mode == SHADERMODE_FLATCOLOR)
5943 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5945 else if (mode == SHADERMODE_LIGHTDIRECTION)
5947 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]);
5948 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]);
5949 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);
5950 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);
5951 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);
5952 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]);
5953 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]);
5957 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]);
5958 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]);
5959 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);
5960 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);
5961 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);
5963 // additive passes are only darkened by fog, not tinted
5964 if (r_glsl_permutation->loc_FogColor >= 0)
5966 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5967 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5969 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5971 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);
5972 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]);
5973 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]);
5974 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5975 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5976 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5977 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5978 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5980 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5981 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5982 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5983 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]);
5984 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]);
5986 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5987 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5988 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5989 if (r_glsl_permutation->loc_Color_Pants >= 0)
5991 if (rsurface.texture->pantstexture)
5992 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5994 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5996 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5998 if (rsurface.texture->shirttexture)
5999 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6001 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
6003 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]);
6004 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
6005 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
6006 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
6007 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6008 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]);
6009 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6011 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
6012 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
6013 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
6014 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
6015 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
6016 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
6017 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
6018 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
6019 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
6020 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
6021 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
6022 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
6023 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
6024 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
6025 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6026 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
6027 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
6028 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6029 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6030 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6031 if (rsurfacepass == RSURFPASS_BACKGROUND)
6033 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6034 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6035 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6039 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6041 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6042 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6043 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
6044 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
6045 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6047 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
6048 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture );
6049 if (rsurface.rtlight)
6051 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6052 if (r_shadow_usingshadowmapcube)
6053 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6054 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6059 case RENDERPATH_CGGL:
6061 if (gl_mesh_separatearrays.integer)
6063 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);
6064 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6065 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6066 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6067 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6068 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6069 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6070 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6074 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);
6075 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6077 R_SetupShader_SetPermutationCG(mode, permutation);
6078 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6079 if (mode == SHADERMODE_LIGHTSOURCE)
6081 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6082 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6086 if (mode == SHADERMODE_LIGHTDIRECTION)
6088 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
6091 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6092 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6093 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6094 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6095 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
6098 if (mode == SHADERMODE_LIGHTSOURCE)
6100 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6101 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6102 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6103 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6104 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
6106 // additive passes are only darkened by fog, not tinted
6107 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6108 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6112 if (mode == SHADERMODE_FLATCOLOR)
6114 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6116 else if (mode == SHADERMODE_LIGHTDIRECTION)
6118 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
6119 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
6120 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
6121 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
6122 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
6123 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
6124 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
6128 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
6129 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
6130 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
6131 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
6132 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
6134 // additive passes are only darkened by fog, not tinted
6135 if (r_cg_permutation->fp_FogColor)
6137 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6138 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6140 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6143 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
6144 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
6145 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
6146 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6147 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6148 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6149 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6150 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6152 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
6153 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
6154 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6155 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6156 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6157 if (r_cg_permutation->fp_Color_Pants)
6159 if (rsurface.texture->pantstexture)
6160 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6162 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6165 if (r_cg_permutation->fp_Color_Shirt)
6167 if (rsurface.texture->shirttexture)
6168 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6170 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6173 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
6174 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6175 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6176 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6177 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6178 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
6179 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6181 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6182 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6183 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6184 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6185 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6186 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6187 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6188 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6189 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6190 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6191 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6192 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6193 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6194 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6195 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
6196 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6197 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6198 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6199 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6200 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6201 if (rsurfacepass == RSURFPASS_BACKGROUND)
6203 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
6204 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
6205 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
6209 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
6211 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6212 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6213 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6214 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6215 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6217 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6218 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
6219 if (rsurface.rtlight)
6221 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6222 if (r_shadow_usingshadowmapcube)
6223 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6224 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6231 case RENDERPATH_GL13:
6232 case RENDERPATH_GL11:
6237 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6239 // select a permutation of the lighting shader appropriate to this
6240 // combination of texture, entity, light source, and fogging, only use the
6241 // minimum features necessary to avoid wasting rendering time in the
6242 // fragment shader on features that are not being used
6243 unsigned int permutation = 0;
6244 unsigned int mode = 0;
6245 const float *lightcolorbase = rtlight->currentcolor;
6246 float ambientscale = rtlight->ambientscale;
6247 float diffusescale = rtlight->diffusescale;
6248 float specularscale = rtlight->specularscale;
6249 // this is the location of the light in view space
6250 vec3_t viewlightorigin;
6251 // this transforms from view space (camera) to light space (cubemap)
6252 matrix4x4_t viewtolight;
6253 matrix4x4_t lighttoview;
6254 float viewtolight16f[16];
6255 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6257 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6258 if (rtlight->currentcubemap != r_texture_whitecube)
6259 permutation |= SHADERPERMUTATION_CUBEFILTER;
6260 if (diffusescale > 0)
6261 permutation |= SHADERPERMUTATION_DIFFUSE;
6262 if (specularscale > 0)
6264 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6265 if (r_shadow_glossexact.integer)
6266 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6268 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6270 if (r_shadow_usingshadowmaprect)
6271 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6272 if (r_shadow_usingshadowmap2d)
6273 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6274 if (r_shadow_usingshadowmapcube)
6275 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6276 else if(r_shadow_shadowmapvsdct)
6277 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6279 if (r_shadow_shadowmapsampler)
6280 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6281 if (r_shadow_shadowmappcf > 1)
6282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6283 else if (r_shadow_shadowmappcf)
6284 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6286 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6287 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6288 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6289 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6290 switch(vid.renderpath)
6292 case RENDERPATH_D3D9:
6294 R_SetupShader_SetPermutationHLSL(mode, permutation);
6295 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6296 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6297 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6298 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6299 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6300 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6301 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6302 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6303 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6304 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6306 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6307 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6308 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6309 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6310 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
6311 if (r_shadow_usingshadowmapcube)
6312 R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6313 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6314 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6317 case RENDERPATH_D3D10:
6318 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6320 case RENDERPATH_D3D11:
6321 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6323 case RENDERPATH_GL20:
6324 R_SetupShader_SetPermutationGLSL(mode, permutation);
6325 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6326 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6327 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);
6328 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);
6329 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);
6330 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]);
6331 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]);
6332 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));
6333 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]);
6334 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6336 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6337 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6338 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6339 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6340 if (r_glsl_permutation->loc_Texture_ShadowMapRect >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT , r_shadow_shadowmaprectangletexture );
6341 if (r_shadow_usingshadowmapcube)
6342 if (r_glsl_permutation->loc_Texture_ShadowMapCube >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6343 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6344 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6346 case RENDERPATH_CGGL:
6348 R_SetupShader_SetPermutationCG(mode, permutation);
6349 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6350 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6351 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
6352 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
6353 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
6354 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
6355 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
6356 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
6357 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
6358 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6360 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6361 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6362 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6363 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6364 if (r_cg_permutation->fp_Texture_ShadowMapRect ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect , r_shadow_shadowmaprectangletexture );CHECKCGERROR
6365 if (r_shadow_usingshadowmapcube)
6366 if (r_cg_permutation->fp_Texture_ShadowMapCube ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6367 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6368 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6371 case RENDERPATH_GL13:
6372 case RENDERPATH_GL11:
6377 #define SKINFRAME_HASH 1024
6381 int loadsequence; // incremented each level change
6382 memexpandablearray_t array;
6383 skinframe_t *hash[SKINFRAME_HASH];
6386 r_skinframe_t r_skinframe;
6388 void R_SkinFrame_PrepareForPurge(void)
6390 r_skinframe.loadsequence++;
6391 // wrap it without hitting zero
6392 if (r_skinframe.loadsequence >= 200)
6393 r_skinframe.loadsequence = 1;
6396 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6400 // mark the skinframe as used for the purging code
6401 skinframe->loadsequence = r_skinframe.loadsequence;
6404 void R_SkinFrame_Purge(void)
6408 for (i = 0;i < SKINFRAME_HASH;i++)
6410 for (s = r_skinframe.hash[i];s;s = s->next)
6412 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6414 if (s->merged == s->base)
6416 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6417 R_PurgeTexture(s->stain );s->stain = NULL;
6418 R_PurgeTexture(s->merged);s->merged = NULL;
6419 R_PurgeTexture(s->base );s->base = NULL;
6420 R_PurgeTexture(s->pants );s->pants = NULL;
6421 R_PurgeTexture(s->shirt );s->shirt = NULL;
6422 R_PurgeTexture(s->nmap );s->nmap = NULL;
6423 R_PurgeTexture(s->gloss );s->gloss = NULL;
6424 R_PurgeTexture(s->glow );s->glow = NULL;
6425 R_PurgeTexture(s->fog );s->fog = NULL;
6426 R_PurgeTexture(s->reflect);s->reflect = NULL;
6427 s->loadsequence = 0;
6433 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6435 char basename[MAX_QPATH];
6437 Image_StripImageExtension(name, basename, sizeof(basename));
6439 if( last == NULL ) {
6441 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6442 item = r_skinframe.hash[hashindex];
6447 // linearly search through the hash bucket
6448 for( ; item ; item = item->next ) {
6449 if( !strcmp( item->basename, basename ) ) {
6456 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6460 char basename[MAX_QPATH];
6462 Image_StripImageExtension(name, basename, sizeof(basename));
6464 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6465 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6466 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6470 rtexture_t *dyntexture;
6471 // check whether its a dynamic texture
6472 dyntexture = CL_GetDynTexture( basename );
6473 if (!add && !dyntexture)
6475 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6476 memset(item, 0, sizeof(*item));
6477 strlcpy(item->basename, basename, sizeof(item->basename));
6478 item->base = dyntexture; // either NULL or dyntexture handle
6479 item->textureflags = textureflags;
6480 item->comparewidth = comparewidth;
6481 item->compareheight = compareheight;
6482 item->comparecrc = comparecrc;
6483 item->next = r_skinframe.hash[hashindex];
6484 r_skinframe.hash[hashindex] = item;
6486 else if( item->base == NULL )
6488 rtexture_t *dyntexture;
6489 // check whether its a dynamic texture
6490 // 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]
6491 dyntexture = CL_GetDynTexture( basename );
6492 item->base = dyntexture; // either NULL or dyntexture handle
6495 R_SkinFrame_MarkUsed(item);
6499 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6501 unsigned long long avgcolor[5], wsum; \
6509 for(pix = 0; pix < cnt; ++pix) \
6512 for(comp = 0; comp < 3; ++comp) \
6514 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6517 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6519 for(comp = 0; comp < 3; ++comp) \
6520 avgcolor[comp] += getpixel * w; \
6523 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6524 avgcolor[4] += getpixel; \
6526 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6528 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6529 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6530 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6531 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6534 extern cvar_t gl_picmip;
6535 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6538 unsigned char *pixels;
6539 unsigned char *bumppixels;
6540 unsigned char *basepixels = NULL;
6541 int basepixels_width = 0;
6542 int basepixels_height = 0;
6543 skinframe_t *skinframe;
6544 rtexture_t *ddsbase = NULL;
6545 qboolean ddshasalpha = false;
6546 float ddsavgcolor[4];
6547 char basename[MAX_QPATH];
6548 int miplevel = R_PicmipForFlags(textureflags);
6549 int savemiplevel = miplevel;
6552 if (cls.state == ca_dedicated)
6555 // return an existing skinframe if already loaded
6556 // if loading of the first image fails, don't make a new skinframe as it
6557 // would cause all future lookups of this to be missing
6558 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6559 if (skinframe && skinframe->base)
6562 Image_StripImageExtension(name, basename, sizeof(basename));
6564 // check for DDS texture file first
6565 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6567 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6568 if (basepixels == NULL)
6572 // FIXME handle miplevel
6574 if (developer_loading.integer)
6575 Con_Printf("loading skin \"%s\"\n", name);
6577 // we've got some pixels to store, so really allocate this new texture now
6579 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6580 skinframe->stain = NULL;
6581 skinframe->merged = NULL;
6582 skinframe->base = NULL;
6583 skinframe->pants = NULL;
6584 skinframe->shirt = NULL;
6585 skinframe->nmap = NULL;
6586 skinframe->gloss = NULL;
6587 skinframe->glow = NULL;
6588 skinframe->fog = NULL;
6589 skinframe->reflect = NULL;
6590 skinframe->hasalpha = false;
6594 skinframe->base = ddsbase;
6595 skinframe->hasalpha = ddshasalpha;
6596 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6597 if (r_loadfog && skinframe->hasalpha)
6598 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6599 //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]);
6603 basepixels_width = image_width;
6604 basepixels_height = image_height;
6605 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);
6606 if (textureflags & TEXF_ALPHA)
6608 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6610 if (basepixels[j] < 255)
6612 skinframe->hasalpha = true;
6616 if (r_loadfog && skinframe->hasalpha)
6618 // has transparent pixels
6619 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6620 for (j = 0;j < image_width * image_height * 4;j += 4)
6625 pixels[j+3] = basepixels[j+3];
6627 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);
6631 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6632 //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]);
6633 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6634 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6635 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6636 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6641 mymiplevel = savemiplevel;
6642 if (r_loadnormalmap)
6643 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);
6644 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6646 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6647 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6648 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6649 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6652 // _norm is the name used by tenebrae and has been adopted as standard
6653 if (r_loadnormalmap && skinframe->nmap == NULL)
6655 mymiplevel = savemiplevel;
6656 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6658 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);
6662 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6664 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6665 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6666 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);
6668 Mem_Free(bumppixels);
6670 else if (r_shadow_bumpscale_basetexture.value > 0)
6672 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6673 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6674 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);
6677 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6678 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6681 // _luma is supported only for tenebrae compatibility
6682 // _glow is the preferred name
6683 mymiplevel = savemiplevel;
6684 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))))
6686 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);
6687 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6688 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6689 Mem_Free(pixels);pixels = NULL;
6692 mymiplevel = savemiplevel;
6693 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6695 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);
6696 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6697 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6702 mymiplevel = savemiplevel;
6703 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6705 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);
6706 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6707 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6712 mymiplevel = savemiplevel;
6713 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6715 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);
6716 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6717 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6722 mymiplevel = savemiplevel;
6723 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6725 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);
6726 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6727 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6733 Mem_Free(basepixels);
6738 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6739 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6742 unsigned char *temp1, *temp2;
6743 skinframe_t *skinframe;
6745 if (cls.state == ca_dedicated)
6748 // if already loaded just return it, otherwise make a new skinframe
6749 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6750 if (skinframe && skinframe->base)
6753 skinframe->stain = NULL;
6754 skinframe->merged = NULL;
6755 skinframe->base = NULL;
6756 skinframe->pants = NULL;
6757 skinframe->shirt = NULL;
6758 skinframe->nmap = NULL;
6759 skinframe->gloss = NULL;
6760 skinframe->glow = NULL;
6761 skinframe->fog = NULL;
6762 skinframe->reflect = NULL;
6763 skinframe->hasalpha = false;
6765 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6769 if (developer_loading.integer)
6770 Con_Printf("loading 32bit skin \"%s\"\n", name);
6772 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6774 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6775 temp2 = temp1 + width * height * 4;
6776 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6777 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);
6780 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6781 if (textureflags & TEXF_ALPHA)
6783 for (i = 3;i < width * height * 4;i += 4)
6785 if (skindata[i] < 255)
6787 skinframe->hasalpha = true;
6791 if (r_loadfog && skinframe->hasalpha)
6793 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6794 memcpy(fogpixels, skindata, width * height * 4);
6795 for (i = 0;i < width * height * 4;i += 4)
6796 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6797 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6798 Mem_Free(fogpixels);
6802 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6803 //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]);
6808 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6812 skinframe_t *skinframe;
6814 if (cls.state == ca_dedicated)
6817 // if already loaded just return it, otherwise make a new skinframe
6818 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6819 if (skinframe && skinframe->base)
6822 skinframe->stain = NULL;
6823 skinframe->merged = NULL;
6824 skinframe->base = NULL;
6825 skinframe->pants = NULL;
6826 skinframe->shirt = NULL;
6827 skinframe->nmap = NULL;
6828 skinframe->gloss = NULL;
6829 skinframe->glow = NULL;
6830 skinframe->fog = NULL;
6831 skinframe->reflect = NULL;
6832 skinframe->hasalpha = false;
6834 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6838 if (developer_loading.integer)
6839 Con_Printf("loading quake skin \"%s\"\n", name);
6841 // 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)
6842 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6843 memcpy(skinframe->qpixels, skindata, width*height);
6844 skinframe->qwidth = width;
6845 skinframe->qheight = height;
6848 for (i = 0;i < width * height;i++)
6849 featuresmask |= palette_featureflags[skindata[i]];
6851 skinframe->hasalpha = false;
6852 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6853 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6854 skinframe->qgeneratemerged = true;
6855 skinframe->qgeneratebase = skinframe->qhascolormapping;
6856 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6858 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6859 //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]);
6864 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6868 unsigned char *skindata;
6870 if (!skinframe->qpixels)
6873 if (!skinframe->qhascolormapping)
6874 colormapped = false;
6878 if (!skinframe->qgeneratebase)
6883 if (!skinframe->qgeneratemerged)
6887 width = skinframe->qwidth;
6888 height = skinframe->qheight;
6889 skindata = skinframe->qpixels;
6891 if (skinframe->qgeneratenmap)
6893 unsigned char *temp1, *temp2;
6894 skinframe->qgeneratenmap = false;
6895 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6896 temp2 = temp1 + width * height * 4;
6897 // use either a custom palette or the quake palette
6898 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6899 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6900 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);
6904 if (skinframe->qgenerateglow)
6906 skinframe->qgenerateglow = false;
6907 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6912 skinframe->qgeneratebase = false;
6913 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);
6914 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6915 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6919 skinframe->qgeneratemerged = false;
6920 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);
6923 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6925 Mem_Free(skinframe->qpixels);
6926 skinframe->qpixels = NULL;
6930 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)
6933 skinframe_t *skinframe;
6935 if (cls.state == ca_dedicated)
6938 // if already loaded just return it, otherwise make a new skinframe
6939 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6940 if (skinframe && skinframe->base)
6943 skinframe->stain = NULL;
6944 skinframe->merged = NULL;
6945 skinframe->base = NULL;
6946 skinframe->pants = NULL;
6947 skinframe->shirt = NULL;
6948 skinframe->nmap = NULL;
6949 skinframe->gloss = NULL;
6950 skinframe->glow = NULL;
6951 skinframe->fog = NULL;
6952 skinframe->reflect = NULL;
6953 skinframe->hasalpha = false;
6955 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6959 if (developer_loading.integer)
6960 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6962 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6963 if (textureflags & TEXF_ALPHA)
6965 for (i = 0;i < width * height;i++)
6967 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6969 skinframe->hasalpha = true;
6973 if (r_loadfog && skinframe->hasalpha)
6974 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6977 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6978 //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]);
6983 skinframe_t *R_SkinFrame_LoadMissing(void)
6985 skinframe_t *skinframe;
6987 if (cls.state == ca_dedicated)
6990 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6991 skinframe->stain = NULL;
6992 skinframe->merged = NULL;
6993 skinframe->base = NULL;
6994 skinframe->pants = NULL;
6995 skinframe->shirt = NULL;
6996 skinframe->nmap = NULL;
6997 skinframe->gloss = NULL;
6998 skinframe->glow = NULL;
6999 skinframe->fog = NULL;
7000 skinframe->reflect = NULL;
7001 skinframe->hasalpha = false;
7003 skinframe->avgcolor[0] = rand() / RAND_MAX;
7004 skinframe->avgcolor[1] = rand() / RAND_MAX;
7005 skinframe->avgcolor[2] = rand() / RAND_MAX;
7006 skinframe->avgcolor[3] = 1;
7011 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7012 typedef struct suffixinfo_s
7015 qboolean flipx, flipy, flipdiagonal;
7018 static suffixinfo_t suffix[3][6] =
7021 {"px", false, false, false},
7022 {"nx", false, false, false},
7023 {"py", false, false, false},
7024 {"ny", false, false, false},
7025 {"pz", false, false, false},
7026 {"nz", false, false, false}
7029 {"posx", false, false, false},
7030 {"negx", false, false, false},
7031 {"posy", false, false, false},
7032 {"negy", false, false, false},
7033 {"posz", false, false, false},
7034 {"negz", false, false, false}
7037 {"rt", true, false, true},
7038 {"lf", false, true, true},
7039 {"ft", true, true, false},
7040 {"bk", false, false, false},
7041 {"up", true, false, true},
7042 {"dn", true, false, true}
7046 static int componentorder[4] = {0, 1, 2, 3};
7048 rtexture_t *R_LoadCubemap(const char *basename)
7050 int i, j, cubemapsize;
7051 unsigned char *cubemappixels, *image_buffer;
7052 rtexture_t *cubemaptexture;
7054 // must start 0 so the first loadimagepixels has no requested width/height
7056 cubemappixels = NULL;
7057 cubemaptexture = NULL;
7058 // keep trying different suffix groups (posx, px, rt) until one loads
7059 for (j = 0;j < 3 && !cubemappixels;j++)
7061 // load the 6 images in the suffix group
7062 for (i = 0;i < 6;i++)
7064 // generate an image name based on the base and and suffix
7065 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7067 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7069 // an image loaded, make sure width and height are equal
7070 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7072 // if this is the first image to load successfully, allocate the cubemap memory
7073 if (!cubemappixels && image_width >= 1)
7075 cubemapsize = image_width;
7076 // note this clears to black, so unavailable sides are black
7077 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7079 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7081 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);
7084 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7086 Mem_Free(image_buffer);
7090 // if a cubemap loaded, upload it
7093 if (developer_loading.integer)
7094 Con_Printf("loading cubemap \"%s\"\n", basename);
7096 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7097 Mem_Free(cubemappixels);
7101 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7102 if (developer_loading.integer)
7104 Con_Printf("(tried tried images ");
7105 for (j = 0;j < 3;j++)
7106 for (i = 0;i < 6;i++)
7107 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7108 Con_Print(" and was unable to find any of them).\n");
7111 return cubemaptexture;
7114 rtexture_t *R_GetCubemap(const char *basename)
7117 for (i = 0;i < r_texture_numcubemaps;i++)
7118 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7119 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7120 if (i >= MAX_CUBEMAPS)
7121 return r_texture_whitecube;
7122 r_texture_numcubemaps++;
7123 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7124 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7125 return r_texture_cubemaps[i].texture;
7128 void R_FreeCubemaps(void)
7131 for (i = 0;i < r_texture_numcubemaps;i++)
7133 if (developer_loading.integer)
7134 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7135 if (r_texture_cubemaps[i].texture)
7136 R_FreeTexture(r_texture_cubemaps[i].texture);
7138 r_texture_numcubemaps = 0;
7141 void R_Main_FreeViewCache(void)
7143 if (r_refdef.viewcache.entityvisible)
7144 Mem_Free(r_refdef.viewcache.entityvisible);
7145 if (r_refdef.viewcache.world_pvsbits)
7146 Mem_Free(r_refdef.viewcache.world_pvsbits);
7147 if (r_refdef.viewcache.world_leafvisible)
7148 Mem_Free(r_refdef.viewcache.world_leafvisible);
7149 if (r_refdef.viewcache.world_surfacevisible)
7150 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7151 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7154 void R_Main_ResizeViewCache(void)
7156 int numentities = r_refdef.scene.numentities;
7157 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7158 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7159 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7160 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7161 if (r_refdef.viewcache.maxentities < numentities)
7163 r_refdef.viewcache.maxentities = numentities;
7164 if (r_refdef.viewcache.entityvisible)
7165 Mem_Free(r_refdef.viewcache.entityvisible);
7166 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7168 if (r_refdef.viewcache.world_numclusters != numclusters)
7170 r_refdef.viewcache.world_numclusters = numclusters;
7171 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7172 if (r_refdef.viewcache.world_pvsbits)
7173 Mem_Free(r_refdef.viewcache.world_pvsbits);
7174 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7176 if (r_refdef.viewcache.world_numleafs != numleafs)
7178 r_refdef.viewcache.world_numleafs = numleafs;
7179 if (r_refdef.viewcache.world_leafvisible)
7180 Mem_Free(r_refdef.viewcache.world_leafvisible);
7181 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7183 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7185 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7186 if (r_refdef.viewcache.world_surfacevisible)
7187 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7188 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7192 extern rtexture_t *loadingscreentexture;
7193 void gl_main_start(void)
7195 loadingscreentexture = NULL;
7196 r_texture_blanknormalmap = NULL;
7197 r_texture_white = NULL;
7198 r_texture_grey128 = NULL;
7199 r_texture_black = NULL;
7200 r_texture_whitecube = NULL;
7201 r_texture_normalizationcube = NULL;
7202 r_texture_fogattenuation = NULL;
7203 r_texture_fogheighttexture = NULL;
7204 r_texture_gammaramps = NULL;
7205 r_texture_numcubemaps = 0;
7207 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7208 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7210 switch(vid.renderpath)
7212 case RENDERPATH_GL20:
7213 case RENDERPATH_CGGL:
7214 case RENDERPATH_D3D9:
7215 case RENDERPATH_D3D10:
7216 case RENDERPATH_D3D11:
7217 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7218 Cvar_SetValueQuick(&gl_combine, 1);
7219 Cvar_SetValueQuick(&r_glsl, 1);
7220 r_loadnormalmap = true;
7224 case RENDERPATH_GL13:
7225 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7226 Cvar_SetValueQuick(&gl_combine, 1);
7227 Cvar_SetValueQuick(&r_glsl, 0);
7228 r_loadnormalmap = false;
7229 r_loadgloss = false;
7232 case RENDERPATH_GL11:
7233 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7234 Cvar_SetValueQuick(&gl_combine, 0);
7235 Cvar_SetValueQuick(&r_glsl, 0);
7236 r_loadnormalmap = false;
7237 r_loadgloss = false;
7243 R_FrameData_Reset();
7247 memset(r_queries, 0, sizeof(r_queries));
7249 r_qwskincache = NULL;
7250 r_qwskincache_size = 0;
7252 // set up r_skinframe loading system for textures
7253 memset(&r_skinframe, 0, sizeof(r_skinframe));
7254 r_skinframe.loadsequence = 1;
7255 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7257 r_main_texturepool = R_AllocTexturePool();
7258 R_BuildBlankTextures();
7260 if (vid.support.arb_texture_cube_map)
7263 R_BuildNormalizationCube();
7265 r_texture_fogattenuation = NULL;
7266 r_texture_fogheighttexture = NULL;
7267 r_texture_gammaramps = NULL;
7268 //r_texture_fogintensity = NULL;
7269 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7270 memset(&r_waterstate, 0, sizeof(r_waterstate));
7271 r_glsl_permutation = NULL;
7272 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7273 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7274 glslshaderstring = NULL;
7276 r_cg_permutation = NULL;
7277 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7278 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7279 cgshaderstring = NULL;
7282 r_hlsl_permutation = NULL;
7283 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7284 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7285 hlslshaderstring = NULL;
7287 memset(&r_svbsp, 0, sizeof (r_svbsp));
7289 r_refdef.fogmasktable_density = 0;
7292 void gl_main_shutdown(void)
7295 R_FrameData_Reset();
7297 R_Main_FreeViewCache();
7299 switch(vid.renderpath)
7301 case RENDERPATH_GL11:
7302 case RENDERPATH_GL13:
7303 case RENDERPATH_GL20:
7304 case RENDERPATH_CGGL:
7306 qglDeleteQueriesARB(r_maxqueries, r_queries);
7308 case RENDERPATH_D3D9:
7309 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7311 case RENDERPATH_D3D10:
7312 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7314 case RENDERPATH_D3D11:
7315 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7321 memset(r_queries, 0, sizeof(r_queries));
7323 r_qwskincache = NULL;
7324 r_qwskincache_size = 0;
7326 // clear out the r_skinframe state
7327 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7328 memset(&r_skinframe, 0, sizeof(r_skinframe));
7331 Mem_Free(r_svbsp.nodes);
7332 memset(&r_svbsp, 0, sizeof (r_svbsp));
7333 R_FreeTexturePool(&r_main_texturepool);
7334 loadingscreentexture = NULL;
7335 r_texture_blanknormalmap = NULL;
7336 r_texture_white = NULL;
7337 r_texture_grey128 = NULL;
7338 r_texture_black = NULL;
7339 r_texture_whitecube = NULL;
7340 r_texture_normalizationcube = NULL;
7341 r_texture_fogattenuation = NULL;
7342 r_texture_fogheighttexture = NULL;
7343 r_texture_gammaramps = NULL;
7344 r_texture_numcubemaps = 0;
7345 //r_texture_fogintensity = NULL;
7346 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7347 memset(&r_waterstate, 0, sizeof(r_waterstate));
7351 extern void CL_ParseEntityLump(char *entitystring);
7352 void gl_main_newmap(void)
7354 // FIXME: move this code to client
7355 char *entities, entname[MAX_QPATH];
7357 Mem_Free(r_qwskincache);
7358 r_qwskincache = NULL;
7359 r_qwskincache_size = 0;
7362 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7363 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7365 CL_ParseEntityLump(entities);
7369 if (cl.worldmodel->brush.entities)
7370 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7372 R_Main_FreeViewCache();
7374 R_FrameData_Reset();
7377 void GL_Main_Init(void)
7379 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7381 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7382 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7383 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7384 if (gamemode == GAME_NEHAHRA)
7386 Cvar_RegisterVariable (&gl_fogenable);
7387 Cvar_RegisterVariable (&gl_fogdensity);
7388 Cvar_RegisterVariable (&gl_fogred);
7389 Cvar_RegisterVariable (&gl_foggreen);
7390 Cvar_RegisterVariable (&gl_fogblue);
7391 Cvar_RegisterVariable (&gl_fogstart);
7392 Cvar_RegisterVariable (&gl_fogend);
7393 Cvar_RegisterVariable (&gl_skyclip);
7395 Cvar_RegisterVariable(&r_motionblur);
7396 Cvar_RegisterVariable(&r_motionblur_maxblur);
7397 Cvar_RegisterVariable(&r_motionblur_bmin);
7398 Cvar_RegisterVariable(&r_motionblur_vmin);
7399 Cvar_RegisterVariable(&r_motionblur_vmax);
7400 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7401 Cvar_RegisterVariable(&r_motionblur_randomize);
7402 Cvar_RegisterVariable(&r_damageblur);
7403 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7404 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7405 Cvar_RegisterVariable(&r_equalize_entities_by);
7406 Cvar_RegisterVariable(&r_equalize_entities_to);
7407 Cvar_RegisterVariable(&r_depthfirst);
7408 Cvar_RegisterVariable(&r_useinfinitefarclip);
7409 Cvar_RegisterVariable(&r_farclip_base);
7410 Cvar_RegisterVariable(&r_farclip_world);
7411 Cvar_RegisterVariable(&r_nearclip);
7412 Cvar_RegisterVariable(&r_showbboxes);
7413 Cvar_RegisterVariable(&r_showsurfaces);
7414 Cvar_RegisterVariable(&r_showtris);
7415 Cvar_RegisterVariable(&r_shownormals);
7416 Cvar_RegisterVariable(&r_showlighting);
7417 Cvar_RegisterVariable(&r_showshadowvolumes);
7418 Cvar_RegisterVariable(&r_showcollisionbrushes);
7419 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7420 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7421 Cvar_RegisterVariable(&r_showdisabledepthtest);
7422 Cvar_RegisterVariable(&r_drawportals);
7423 Cvar_RegisterVariable(&r_drawentities);
7424 Cvar_RegisterVariable(&r_draw2d);
7425 Cvar_RegisterVariable(&r_drawworld);
7426 Cvar_RegisterVariable(&r_cullentities_trace);
7427 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7428 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7429 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7430 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7431 Cvar_RegisterVariable(&r_drawviewmodel);
7432 Cvar_RegisterVariable(&r_drawexteriormodel);
7433 Cvar_RegisterVariable(&r_speeds);
7434 Cvar_RegisterVariable(&r_fullbrights);
7435 Cvar_RegisterVariable(&r_wateralpha);
7436 Cvar_RegisterVariable(&r_dynamic);
7437 Cvar_RegisterVariable(&r_fullbright);
7438 Cvar_RegisterVariable(&r_shadows);
7439 Cvar_RegisterVariable(&r_shadows_darken);
7440 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7441 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7442 Cvar_RegisterVariable(&r_shadows_throwdistance);
7443 Cvar_RegisterVariable(&r_shadows_throwdirection);
7444 Cvar_RegisterVariable(&r_shadows_focus);
7445 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7446 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7447 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7448 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7449 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7450 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7451 Cvar_RegisterVariable(&r_fog_exp2);
7452 Cvar_RegisterVariable(&r_drawfog);
7453 Cvar_RegisterVariable(&r_transparentdepthmasking);
7454 Cvar_RegisterVariable(&r_texture_dds_load);
7455 Cvar_RegisterVariable(&r_texture_dds_save);
7456 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7457 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7458 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7459 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7460 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7461 Cvar_RegisterVariable(&r_textureunits);
7462 Cvar_RegisterVariable(&gl_combine);
7463 Cvar_RegisterVariable(&r_glsl);
7464 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7465 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7466 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7467 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7468 Cvar_RegisterVariable(&r_glsl_postprocess);
7469 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7470 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7471 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7472 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7473 Cvar_RegisterVariable(&r_water);
7474 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7475 Cvar_RegisterVariable(&r_water_clippingplanebias);
7476 Cvar_RegisterVariable(&r_water_refractdistort);
7477 Cvar_RegisterVariable(&r_water_reflectdistort);
7478 Cvar_RegisterVariable(&r_lerpsprites);
7479 Cvar_RegisterVariable(&r_lerpmodels);
7480 Cvar_RegisterVariable(&r_lerplightstyles);
7481 Cvar_RegisterVariable(&r_waterscroll);
7482 Cvar_RegisterVariable(&r_bloom);
7483 Cvar_RegisterVariable(&r_bloom_colorscale);
7484 Cvar_RegisterVariable(&r_bloom_brighten);
7485 Cvar_RegisterVariable(&r_bloom_blur);
7486 Cvar_RegisterVariable(&r_bloom_resolution);
7487 Cvar_RegisterVariable(&r_bloom_colorexponent);
7488 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7489 Cvar_RegisterVariable(&r_hdr);
7490 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7491 Cvar_RegisterVariable(&r_hdr_glowintensity);
7492 Cvar_RegisterVariable(&r_hdr_range);
7493 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7494 Cvar_RegisterVariable(&developer_texturelogging);
7495 Cvar_RegisterVariable(&gl_lightmaps);
7496 Cvar_RegisterVariable(&r_test);
7497 Cvar_RegisterVariable(&r_glsl_saturation);
7498 Cvar_RegisterVariable(&r_framedatasize);
7499 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7500 Cvar_SetValue("r_fullbrights", 0);
7501 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7503 Cvar_RegisterVariable(&r_track_sprites);
7504 Cvar_RegisterVariable(&r_track_sprites_flags);
7505 Cvar_RegisterVariable(&r_track_sprites_scalew);
7506 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7507 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7508 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7511 extern void R_Textures_Init(void);
7512 extern void GL_Draw_Init(void);
7513 extern void GL_Main_Init(void);
7514 extern void R_Shadow_Init(void);
7515 extern void R_Sky_Init(void);
7516 extern void GL_Surf_Init(void);
7517 extern void R_Particles_Init(void);
7518 extern void R_Explosion_Init(void);
7519 extern void gl_backend_init(void);
7520 extern void Sbar_Init(void);
7521 extern void R_LightningBeams_Init(void);
7522 extern void Mod_RenderInit(void);
7523 extern void Font_Init(void);
7525 void Render_Init(void)
7538 R_LightningBeams_Init();
7547 extern char *ENGINE_EXTENSIONS;
7550 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7551 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7552 gl_version = (const char *)qglGetString(GL_VERSION);
7553 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7557 if (!gl_platformextensions)
7558 gl_platformextensions = "";
7560 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7561 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7562 Con_Printf("GL_VERSION: %s\n", gl_version);
7563 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7564 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7566 VID_CheckExtensions();
7568 // LordHavoc: report supported extensions
7569 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7571 // clear to black (loading plaque will be seen over this)
7572 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7575 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7579 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7581 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7584 p = r_refdef.view.frustum + i;
7589 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7593 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7597 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7601 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7605 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7609 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7613 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7617 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7625 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7629 for (i = 0;i < numplanes;i++)
7636 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7640 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7644 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7648 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7652 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7656 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7660 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7664 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7672 //==================================================================================
7674 // LordHavoc: this stores temporary data used within the same frame
7676 qboolean r_framedata_failed;
7677 static size_t r_framedata_size;
7678 static size_t r_framedata_current;
7679 static void *r_framedata_base;
7681 void R_FrameData_Reset(void)
7683 if (r_framedata_base)
7684 Mem_Free(r_framedata_base);
7685 r_framedata_base = NULL;
7686 r_framedata_size = 0;
7687 r_framedata_current = 0;
7688 r_framedata_failed = false;
7691 void R_FrameData_NewFrame(void)
7694 if (r_framedata_failed)
7695 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7696 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7697 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7698 if (r_framedata_size != wantedsize)
7700 r_framedata_size = wantedsize;
7701 if (r_framedata_base)
7702 Mem_Free(r_framedata_base);
7703 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7705 r_framedata_current = 0;
7706 r_framedata_failed = false;
7709 void *R_FrameData_Alloc(size_t size)
7713 // align to 16 byte boundary
7714 size = (size + 15) & ~15;
7715 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7716 r_framedata_current += size;
7719 if (r_framedata_current > r_framedata_size)
7720 r_framedata_failed = true;
7722 // return NULL on everything after a failure
7723 if (r_framedata_failed)
7729 void *R_FrameData_Store(size_t size, void *data)
7731 void *d = R_FrameData_Alloc(size);
7733 memcpy(d, data, size);
7737 //==================================================================================
7739 // LordHavoc: animcache originally written by Echon, rewritten since then
7742 * Animation cache prevents re-generating mesh data for an animated model
7743 * multiple times in one frame for lighting, shadowing, reflections, etc.
7746 void R_AnimCache_Free(void)
7750 void R_AnimCache_ClearCache(void)
7753 entity_render_t *ent;
7755 for (i = 0;i < r_refdef.scene.numentities;i++)
7757 ent = r_refdef.scene.entities[i];
7758 ent->animcache_vertex3f = NULL;
7759 ent->animcache_normal3f = NULL;
7760 ent->animcache_svector3f = NULL;
7761 ent->animcache_tvector3f = NULL;
7762 ent->animcache_vertexposition = NULL;
7763 ent->animcache_vertexmesh = NULL;
7764 ent->animcache_vertexpositionbuffer = NULL;
7765 ent->animcache_vertexmeshbuffer = NULL;
7769 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7773 // identical memory layout, so no need to allocate...
7774 // this also provides the vertexposition structure to everything, e.g.
7775 // depth masked rendering currently uses it even if having separate
7777 // NOTE: get rid of this optimization if changing it to e.g. 4f
7778 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7781 // get rid of following uses of VERTEXPOSITION, change to the array:
7782 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7783 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7784 // R_DrawTextureSurfaceList_DepthOnly
7785 // R_Q1BSP_DrawShadowMap
7787 switch(vid.renderpath)
7789 case RENDERPATH_GL20:
7790 case RENDERPATH_CGGL:
7791 // need the meshbuffers if !gl_mesh_separatearrays.integer
7792 if (gl_mesh_separatearrays.integer)
7795 case RENDERPATH_D3D9:
7796 case RENDERPATH_D3D10:
7797 case RENDERPATH_D3D11:
7798 // always need the meshbuffers
7800 case RENDERPATH_GL13:
7801 case RENDERPATH_GL11:
7802 // never need the meshbuffers
7806 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7807 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7809 if (!ent->animcache_vertexposition)
7810 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7812 if (ent->animcache_vertexposition)
7815 for (i = 0;i < numvertices;i++)
7816 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7818 // TODO: upload vertex buffer?
7820 if (ent->animcache_vertexmesh)
7822 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7823 for (i = 0;i < numvertices;i++)
7824 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7825 if (ent->animcache_svector3f)
7826 for (i = 0;i < numvertices;i++)
7827 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7828 if (ent->animcache_tvector3f)
7829 for (i = 0;i < numvertices;i++)
7830 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7831 if (ent->animcache_normal3f)
7832 for (i = 0;i < numvertices;i++)
7833 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7834 // TODO: upload vertex buffer?
7838 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7840 dp_model_t *model = ent->model;
7842 // see if it's already cached this frame
7843 if (ent->animcache_vertex3f)
7845 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7846 if (wantnormals || wanttangents)
7848 if (ent->animcache_normal3f)
7849 wantnormals = false;
7850 if (ent->animcache_svector3f)
7851 wanttangents = false;
7852 if (wantnormals || wanttangents)
7854 numvertices = model->surfmesh.num_vertices;
7856 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7859 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7860 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7862 if (!r_framedata_failed)
7864 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7865 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7872 // see if this ent is worth caching
7873 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7875 // get some memory for this entity and generate mesh data
7876 numvertices = model->surfmesh.num_vertices;
7877 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7879 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7882 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7883 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7885 if (!r_framedata_failed)
7887 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7888 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7891 return !r_framedata_failed;
7894 void R_AnimCache_CacheVisibleEntities(void)
7897 qboolean wantnormals = true;
7898 qboolean wanttangents = !r_showsurfaces.integer;
7900 switch(vid.renderpath)
7902 case RENDERPATH_GL20:
7903 case RENDERPATH_CGGL:
7904 case RENDERPATH_D3D9:
7905 case RENDERPATH_D3D10:
7906 case RENDERPATH_D3D11:
7908 case RENDERPATH_GL13:
7909 case RENDERPATH_GL11:
7910 wanttangents = false;
7914 if (r_shownormals.integer)
7915 wanttangents = wantnormals = true;
7917 // TODO: thread this
7918 // NOTE: R_PrepareRTLights() also caches entities
7920 for (i = 0;i < r_refdef.scene.numentities;i++)
7921 if (r_refdef.viewcache.entityvisible[i])
7922 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7925 //==================================================================================
7927 static void R_View_UpdateEntityLighting (void)
7930 entity_render_t *ent;
7931 vec3_t tempdiffusenormal, avg;
7932 vec_t f, fa, fd, fdd;
7933 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7935 for (i = 0;i < r_refdef.scene.numentities;i++)
7937 ent = r_refdef.scene.entities[i];
7939 // skip unseen models
7940 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7944 if (ent->model && ent->model->brush.num_leafs)
7946 // TODO: use modellight for r_ambient settings on world?
7947 VectorSet(ent->modellight_ambient, 0, 0, 0);
7948 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7949 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7953 // fetch the lighting from the worldmodel data
7954 VectorClear(ent->modellight_ambient);
7955 VectorClear(ent->modellight_diffuse);
7956 VectorClear(tempdiffusenormal);
7957 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7960 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7961 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7962 if(ent->flags & RENDER_EQUALIZE)
7964 // first fix up ambient lighting...
7965 if(r_equalize_entities_minambient.value > 0)
7967 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7970 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7971 if(fa < r_equalize_entities_minambient.value * fd)
7974 // fa'/fd' = minambient
7975 // fa'+0.25*fd' = fa+0.25*fd
7977 // fa' = fd' * minambient
7978 // fd'*(0.25+minambient) = fa+0.25*fd
7980 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7981 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7983 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7984 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
7985 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7986 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7991 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7993 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7994 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7997 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7998 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7999 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8005 VectorSet(ent->modellight_ambient, 1, 1, 1);
8007 // move the light direction into modelspace coordinates for lighting code
8008 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8009 if(VectorLength2(ent->modellight_lightdir) == 0)
8010 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8011 VectorNormalize(ent->modellight_lightdir);
8015 #define MAX_LINEOFSIGHTTRACES 64
8017 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8020 vec3_t boxmins, boxmaxs;
8023 dp_model_t *model = r_refdef.scene.worldmodel;
8025 if (!model || !model->brush.TraceLineOfSight)
8028 // expand the box a little
8029 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8030 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8031 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8032 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8033 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8034 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8036 // return true if eye is inside enlarged box
8037 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8041 VectorCopy(eye, start);
8042 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8043 if (model->brush.TraceLineOfSight(model, start, end))
8046 // try various random positions
8047 for (i = 0;i < numsamples;i++)
8049 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8050 if (model->brush.TraceLineOfSight(model, start, end))
8058 static void R_View_UpdateEntityVisible (void)
8063 entity_render_t *ent;
8065 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8066 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8067 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8068 : RENDER_EXTERIORMODEL;
8069 if (!r_drawviewmodel.integer)
8070 renderimask |= RENDER_VIEWMODEL;
8071 if (!r_drawexteriormodel.integer)
8072 renderimask |= RENDER_EXTERIORMODEL;
8073 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8075 // worldmodel can check visibility
8076 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8077 for (i = 0;i < r_refdef.scene.numentities;i++)
8079 ent = r_refdef.scene.entities[i];
8080 if (!(ent->flags & renderimask))
8081 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)))
8082 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))
8083 r_refdef.viewcache.entityvisible[i] = true;
8085 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8086 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8088 for (i = 0;i < r_refdef.scene.numentities;i++)
8090 ent = r_refdef.scene.entities[i];
8091 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8093 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8095 continue; // temp entities do pvs only
8096 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8097 ent->last_trace_visibility = realtime;
8098 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8099 r_refdef.viewcache.entityvisible[i] = 0;
8106 // no worldmodel or it can't check visibility
8107 for (i = 0;i < r_refdef.scene.numentities;i++)
8109 ent = r_refdef.scene.entities[i];
8110 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));
8115 /// only used if skyrendermasked, and normally returns false
8116 int R_DrawBrushModelsSky (void)
8119 entity_render_t *ent;
8122 for (i = 0;i < r_refdef.scene.numentities;i++)
8124 if (!r_refdef.viewcache.entityvisible[i])
8126 ent = r_refdef.scene.entities[i];
8127 if (!ent->model || !ent->model->DrawSky)
8129 ent->model->DrawSky(ent);
8135 static void R_DrawNoModel(entity_render_t *ent);
8136 static void R_DrawModels(void)
8139 entity_render_t *ent;
8141 for (i = 0;i < r_refdef.scene.numentities;i++)
8143 if (!r_refdef.viewcache.entityvisible[i])
8145 ent = r_refdef.scene.entities[i];
8146 r_refdef.stats.entities++;
8147 if (ent->model && ent->model->Draw != NULL)
8148 ent->model->Draw(ent);
8154 static void R_DrawModelsDepth(void)
8157 entity_render_t *ent;
8159 for (i = 0;i < r_refdef.scene.numentities;i++)
8161 if (!r_refdef.viewcache.entityvisible[i])
8163 ent = r_refdef.scene.entities[i];
8164 if (ent->model && ent->model->DrawDepth != NULL)
8165 ent->model->DrawDepth(ent);
8169 static void R_DrawModelsDebug(void)
8172 entity_render_t *ent;
8174 for (i = 0;i < r_refdef.scene.numentities;i++)
8176 if (!r_refdef.viewcache.entityvisible[i])
8178 ent = r_refdef.scene.entities[i];
8179 if (ent->model && ent->model->DrawDebug != NULL)
8180 ent->model->DrawDebug(ent);
8184 static void R_DrawModelsAddWaterPlanes(void)
8187 entity_render_t *ent;
8189 for (i = 0;i < r_refdef.scene.numentities;i++)
8191 if (!r_refdef.viewcache.entityvisible[i])
8193 ent = r_refdef.scene.entities[i];
8194 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8195 ent->model->DrawAddWaterPlanes(ent);
8199 static void R_View_SetFrustum(void)
8202 double slopex, slopey;
8203 vec3_t forward, left, up, origin;
8205 // we can't trust r_refdef.view.forward and friends in reflected scenes
8206 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8209 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8210 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8211 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8212 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8213 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8214 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8215 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8216 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8217 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8218 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8219 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8220 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8224 zNear = r_refdef.nearclip;
8225 nudge = 1.0 - 1.0 / (1<<23);
8226 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8227 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8228 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8229 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8230 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8231 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8232 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8233 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8239 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8240 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8241 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8242 r_refdef.view.frustum[0].dist = m[15] - m[12];
8244 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8245 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8246 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8247 r_refdef.view.frustum[1].dist = m[15] + m[12];
8249 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8250 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8251 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8252 r_refdef.view.frustum[2].dist = m[15] - m[13];
8254 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8255 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8256 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8257 r_refdef.view.frustum[3].dist = m[15] + m[13];
8259 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8260 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8261 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8262 r_refdef.view.frustum[4].dist = m[15] - m[14];
8264 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8265 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8266 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8267 r_refdef.view.frustum[5].dist = m[15] + m[14];
8270 if (r_refdef.view.useperspective)
8272 slopex = 1.0 / r_refdef.view.frustum_x;
8273 slopey = 1.0 / r_refdef.view.frustum_y;
8274 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8275 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
8276 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
8277 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
8278 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8280 // Leaving those out was a mistake, those were in the old code, and they
8281 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8282 // I couldn't reproduce it after adding those normalizations. --blub
8283 VectorNormalize(r_refdef.view.frustum[0].normal);
8284 VectorNormalize(r_refdef.view.frustum[1].normal);
8285 VectorNormalize(r_refdef.view.frustum[2].normal);
8286 VectorNormalize(r_refdef.view.frustum[3].normal);
8288 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8289 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]);
8290 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]);
8291 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]);
8292 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]);
8294 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8295 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8296 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8297 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8298 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8302 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8303 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8304 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8305 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8306 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8307 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8308 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8309 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8310 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8311 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8313 r_refdef.view.numfrustumplanes = 5;
8315 if (r_refdef.view.useclipplane)
8317 r_refdef.view.numfrustumplanes = 6;
8318 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8321 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8322 PlaneClassify(r_refdef.view.frustum + i);
8324 // LordHavoc: note to all quake engine coders, Quake had a special case
8325 // for 90 degrees which assumed a square view (wrong), so I removed it,
8326 // Quake2 has it disabled as well.
8328 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8329 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8330 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8331 //PlaneClassify(&frustum[0]);
8333 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8334 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8335 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8336 //PlaneClassify(&frustum[1]);
8338 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8339 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8340 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8341 //PlaneClassify(&frustum[2]);
8343 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8344 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8345 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8346 //PlaneClassify(&frustum[3]);
8349 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8350 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8351 //PlaneClassify(&frustum[4]);
8354 void R_View_Update(void)
8356 R_Main_ResizeViewCache();
8357 R_View_SetFrustum();
8358 R_View_WorldVisibility(r_refdef.view.useclipplane);
8359 R_View_UpdateEntityVisible();
8360 R_View_UpdateEntityLighting();
8363 void R_SetupView(qboolean allowwaterclippingplane)
8365 const float *customclipplane = NULL;
8367 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8369 // LordHavoc: couldn't figure out how to make this approach the
8370 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8371 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8372 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8373 dist = r_refdef.view.clipplane.dist;
8374 plane[0] = r_refdef.view.clipplane.normal[0];
8375 plane[1] = r_refdef.view.clipplane.normal[1];
8376 plane[2] = r_refdef.view.clipplane.normal[2];
8378 customclipplane = plane;
8381 if (!r_refdef.view.useperspective)
8382 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);
8383 else if (vid.stencil && r_useinfinitefarclip.integer)
8384 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);
8386 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);
8387 R_SetViewport(&r_refdef.view.viewport);
8390 void R_EntityMatrix(const matrix4x4_t *matrix)
8392 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8394 gl_modelmatrixchanged = false;
8395 gl_modelmatrix = *matrix;
8396 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8397 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8398 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8399 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8401 switch(vid.renderpath)
8403 case RENDERPATH_D3D9:
8405 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8406 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8409 case RENDERPATH_D3D10:
8410 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8412 case RENDERPATH_D3D11:
8413 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8415 case RENDERPATH_GL20:
8416 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8417 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8418 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8420 case RENDERPATH_CGGL:
8423 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8424 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8425 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8428 case RENDERPATH_GL13:
8429 case RENDERPATH_GL11:
8430 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8436 void R_ResetViewRendering2D(void)
8438 r_viewport_t viewport;
8441 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8442 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);
8443 R_SetViewport(&viewport);
8444 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8445 GL_Color(1, 1, 1, 1);
8446 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8447 GL_BlendFunc(GL_ONE, GL_ZERO);
8448 GL_AlphaTest(false);
8449 GL_ScissorTest(false);
8450 GL_DepthMask(false);
8451 GL_DepthRange(0, 1);
8452 GL_DepthTest(false);
8453 GL_DepthFunc(GL_LEQUAL);
8454 R_EntityMatrix(&identitymatrix);
8455 R_Mesh_ResetTextureState();
8456 GL_PolygonOffset(0, 0);
8457 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8458 switch(vid.renderpath)
8460 case RENDERPATH_GL11:
8461 case RENDERPATH_GL13:
8462 case RENDERPATH_GL20:
8463 case RENDERPATH_CGGL:
8464 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8466 case RENDERPATH_D3D9:
8467 case RENDERPATH_D3D10:
8468 case RENDERPATH_D3D11:
8471 GL_CullFace(GL_NONE);
8474 void R_ResetViewRendering3D(void)
8479 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8480 GL_Color(1, 1, 1, 1);
8481 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8482 GL_BlendFunc(GL_ONE, GL_ZERO);
8483 GL_AlphaTest(false);
8484 GL_ScissorTest(true);
8486 GL_DepthRange(0, 1);
8488 GL_DepthFunc(GL_LEQUAL);
8489 R_EntityMatrix(&identitymatrix);
8490 R_Mesh_ResetTextureState();
8491 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8492 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8493 switch(vid.renderpath)
8495 case RENDERPATH_GL11:
8496 case RENDERPATH_GL13:
8497 case RENDERPATH_GL20:
8498 case RENDERPATH_CGGL:
8499 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8501 case RENDERPATH_D3D9:
8502 case RENDERPATH_D3D10:
8503 case RENDERPATH_D3D11:
8506 GL_CullFace(r_refdef.view.cullface_back);
8511 R_RenderView_UpdateViewVectors
8514 static void R_RenderView_UpdateViewVectors(void)
8516 // break apart the view matrix into vectors for various purposes
8517 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8518 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8519 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8520 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8521 // make an inverted copy of the view matrix for tracking sprites
8522 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8525 void R_RenderScene(void);
8526 void R_RenderWaterPlanes(void);
8528 static void R_Water_StartFrame(void)
8531 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8532 r_waterstate_waterplane_t *p;
8534 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8537 switch(vid.renderpath)
8539 case RENDERPATH_GL20:
8540 case RENDERPATH_CGGL:
8541 case RENDERPATH_D3D9:
8542 case RENDERPATH_D3D10:
8543 case RENDERPATH_D3D11:
8545 case RENDERPATH_GL13:
8546 case RENDERPATH_GL11:
8550 // set waterwidth and waterheight to the water resolution that will be
8551 // used (often less than the screen resolution for faster rendering)
8552 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8553 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8555 // calculate desired texture sizes
8556 // can't use water if the card does not support the texture size
8557 if (!r_water.integer || r_showsurfaces.integer)
8558 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8559 else if (vid.support.arb_texture_non_power_of_two)
8561 texturewidth = waterwidth;
8562 textureheight = waterheight;
8563 camerawidth = waterwidth;
8564 cameraheight = waterheight;
8568 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8569 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8570 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8571 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8574 // allocate textures as needed
8575 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8577 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8578 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8580 if (p->texture_refraction)
8581 R_FreeTexture(p->texture_refraction);
8582 p->texture_refraction = NULL;
8583 if (p->texture_reflection)
8584 R_FreeTexture(p->texture_reflection);
8585 p->texture_reflection = NULL;
8586 if (p->texture_camera)
8587 R_FreeTexture(p->texture_camera);
8588 p->texture_camera = NULL;
8590 memset(&r_waterstate, 0, sizeof(r_waterstate));
8591 r_waterstate.texturewidth = texturewidth;
8592 r_waterstate.textureheight = textureheight;
8593 r_waterstate.camerawidth = camerawidth;
8594 r_waterstate.cameraheight = cameraheight;
8597 if (r_waterstate.texturewidth)
8599 r_waterstate.enabled = true;
8601 // when doing a reduced render (HDR) we want to use a smaller area
8602 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8603 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8605 // set up variables that will be used in shader setup
8606 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8607 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8608 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8609 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8612 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8613 r_waterstate.numwaterplanes = 0;
8616 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8618 int triangleindex, planeindex;
8625 r_waterstate_waterplane_t *p;
8626 texture_t *t = R_GetCurrentTexture(surface->texture);
8627 cam_ent = t->camera_entity;
8628 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8631 // just use the first triangle with a valid normal for any decisions
8632 VectorClear(normal);
8633 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8635 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8636 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8637 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8638 TriangleNormal(vert[0], vert[1], vert[2], normal);
8639 if (VectorLength2(normal) >= 0.001)
8643 VectorCopy(normal, plane.normal);
8644 VectorNormalize(plane.normal);
8645 plane.dist = DotProduct(vert[0], plane.normal);
8646 PlaneClassify(&plane);
8647 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8649 // skip backfaces (except if nocullface is set)
8650 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8652 VectorNegate(plane.normal, plane.normal);
8654 PlaneClassify(&plane);
8658 // find a matching plane if there is one
8659 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8660 if(p->camera_entity == t->camera_entity)
8661 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8663 if (planeindex >= r_waterstate.maxwaterplanes)
8664 return; // nothing we can do, out of planes
8666 // if this triangle does not fit any known plane rendered this frame, add one
8667 if (planeindex >= r_waterstate.numwaterplanes)
8669 // store the new plane
8670 r_waterstate.numwaterplanes++;
8672 // clear materialflags and pvs
8673 p->materialflags = 0;
8674 p->pvsvalid = false;
8675 p->camera_entity = t->camera_entity;
8677 // merge this surface's materialflags into the waterplane
8678 p->materialflags |= t->currentmaterialflags;
8679 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8681 // merge this surface's PVS into the waterplane
8682 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8683 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8684 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8686 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8692 static void R_Water_ProcessPlanes(void)
8694 r_refdef_view_t originalview;
8695 r_refdef_view_t myview;
8697 r_waterstate_waterplane_t *p;
8700 originalview = r_refdef.view;
8702 // make sure enough textures are allocated
8703 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8705 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8707 if (!p->texture_refraction)
8708 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);
8709 if (!p->texture_refraction)
8712 else if (p->materialflags & MATERIALFLAG_CAMERA)
8714 if (!p->texture_camera)
8715 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);
8716 if (!p->texture_camera)
8720 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8722 if (!p->texture_reflection)
8723 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);
8724 if (!p->texture_reflection)
8730 r_refdef.view = originalview;
8731 r_refdef.view.showdebug = false;
8732 r_refdef.view.width = r_waterstate.waterwidth;
8733 r_refdef.view.height = r_waterstate.waterheight;
8734 r_refdef.view.useclipplane = true;
8735 myview = r_refdef.view;
8736 r_waterstate.renderingscene = true;
8737 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8739 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8741 r_refdef.view = myview;
8742 // render reflected scene and copy into texture
8743 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8744 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8745 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8746 r_refdef.view.clipplane = p->plane;
8747 // reverse the cullface settings for this render
8748 r_refdef.view.cullface_front = GL_FRONT;
8749 r_refdef.view.cullface_back = GL_BACK;
8750 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8752 r_refdef.view.usecustompvs = true;
8754 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8756 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8759 R_ResetViewRendering3D();
8760 R_ClearScreen(r_refdef.fogenabled);
8764 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);
8767 // render the normal view scene and copy into texture
8768 // (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)
8769 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8771 r_waterstate.renderingrefraction = true;
8772 r_refdef.view = myview;
8774 r_refdef.view.clipplane = p->plane;
8775 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8776 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8778 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8780 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8781 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8782 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8783 R_RenderView_UpdateViewVectors();
8784 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8786 r_refdef.view.usecustompvs = true;
8787 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);
8791 PlaneClassify(&r_refdef.view.clipplane);
8793 R_ResetViewRendering3D();
8794 R_ClearScreen(r_refdef.fogenabled);
8798 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);
8799 r_waterstate.renderingrefraction = false;
8801 else if (p->materialflags & MATERIALFLAG_CAMERA)
8803 r_refdef.view = myview;
8805 r_refdef.view.clipplane = p->plane;
8806 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8807 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8809 r_refdef.view.width = r_waterstate.camerawidth;
8810 r_refdef.view.height = r_waterstate.cameraheight;
8811 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8812 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8814 if(p->camera_entity)
8816 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8817 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8820 // reverse the cullface settings for this render
8821 r_refdef.view.cullface_front = GL_FRONT;
8822 r_refdef.view.cullface_back = GL_BACK;
8823 // also reverse the view matrix
8824 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
8825 R_RenderView_UpdateViewVectors();
8826 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8828 r_refdef.view.usecustompvs = true;
8829 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);
8832 // camera needs no clipplane
8833 r_refdef.view.useclipplane = false;
8835 PlaneClassify(&r_refdef.view.clipplane);
8837 R_ResetViewRendering3D();
8838 R_ClearScreen(r_refdef.fogenabled);
8842 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);
8843 r_waterstate.renderingrefraction = false;
8847 r_waterstate.renderingscene = false;
8848 r_refdef.view = originalview;
8849 R_ResetViewRendering3D();
8850 R_ClearScreen(r_refdef.fogenabled);
8854 r_refdef.view = originalview;
8855 r_waterstate.renderingscene = false;
8856 Cvar_SetValueQuick(&r_water, 0);
8857 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8861 void R_Bloom_StartFrame(void)
8863 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8865 switch(vid.renderpath)
8867 case RENDERPATH_GL20:
8868 case RENDERPATH_CGGL:
8869 case RENDERPATH_D3D9:
8870 case RENDERPATH_D3D10:
8871 case RENDERPATH_D3D11:
8873 case RENDERPATH_GL13:
8874 case RENDERPATH_GL11:
8878 // set bloomwidth and bloomheight to the bloom resolution that will be
8879 // used (often less than the screen resolution for faster rendering)
8880 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8881 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8882 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8883 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8884 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8886 // calculate desired texture sizes
8887 if (vid.support.arb_texture_non_power_of_two)
8889 screentexturewidth = r_refdef.view.width;
8890 screentextureheight = r_refdef.view.height;
8891 bloomtexturewidth = r_bloomstate.bloomwidth;
8892 bloomtextureheight = r_bloomstate.bloomheight;
8896 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8897 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8898 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8899 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8902 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))
8904 Cvar_SetValueQuick(&r_hdr, 0);
8905 Cvar_SetValueQuick(&r_bloom, 0);
8906 Cvar_SetValueQuick(&r_motionblur, 0);
8907 Cvar_SetValueQuick(&r_damageblur, 0);
8910 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)))
8911 screentexturewidth = screentextureheight = 0;
8912 if (!r_hdr.integer && !r_bloom.integer)
8913 bloomtexturewidth = bloomtextureheight = 0;
8915 // allocate textures as needed
8916 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8918 if (r_bloomstate.texture_screen)
8919 R_FreeTexture(r_bloomstate.texture_screen);
8920 r_bloomstate.texture_screen = NULL;
8921 r_bloomstate.screentexturewidth = screentexturewidth;
8922 r_bloomstate.screentextureheight = screentextureheight;
8923 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8924 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);
8926 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8928 if (r_bloomstate.texture_bloom)
8929 R_FreeTexture(r_bloomstate.texture_bloom);
8930 r_bloomstate.texture_bloom = NULL;
8931 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8932 r_bloomstate.bloomtextureheight = bloomtextureheight;
8933 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8934 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);
8937 // when doing a reduced render (HDR) we want to use a smaller area
8938 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8939 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8940 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8941 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8942 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8944 // set up a texcoord array for the full resolution screen image
8945 // (we have to keep this around to copy back during final render)
8946 r_bloomstate.screentexcoord2f[0] = 0;
8947 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8948 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8949 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8950 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8951 r_bloomstate.screentexcoord2f[5] = 0;
8952 r_bloomstate.screentexcoord2f[6] = 0;
8953 r_bloomstate.screentexcoord2f[7] = 0;
8955 // set up a texcoord array for the reduced resolution bloom image
8956 // (which will be additive blended over the screen image)
8957 r_bloomstate.bloomtexcoord2f[0] = 0;
8958 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8959 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8960 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8961 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8962 r_bloomstate.bloomtexcoord2f[5] = 0;
8963 r_bloomstate.bloomtexcoord2f[6] = 0;
8964 r_bloomstate.bloomtexcoord2f[7] = 0;
8966 switch(vid.renderpath)
8968 case RENDERPATH_GL11:
8969 case RENDERPATH_GL13:
8970 case RENDERPATH_GL20:
8971 case RENDERPATH_CGGL:
8973 case RENDERPATH_D3D9:
8974 case RENDERPATH_D3D10:
8975 case RENDERPATH_D3D11:
8978 for (i = 0;i < 4;i++)
8980 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8981 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8982 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8983 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8989 if (r_hdr.integer || r_bloom.integer)
8991 r_bloomstate.enabled = true;
8992 r_bloomstate.hdr = r_hdr.integer != 0;
8995 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);
8998 void R_Bloom_CopyBloomTexture(float colorscale)
9000 r_refdef.stats.bloom++;
9002 // scale down screen texture to the bloom texture size
9004 R_SetViewport(&r_bloomstate.viewport);
9005 GL_BlendFunc(GL_ONE, GL_ZERO);
9006 GL_Color(colorscale, colorscale, colorscale, 1);
9007 // 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...
9008 switch(vid.renderpath)
9010 case RENDERPATH_GL11:
9011 case RENDERPATH_GL13:
9012 case RENDERPATH_GL20:
9013 case RENDERPATH_CGGL:
9014 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9016 case RENDERPATH_D3D9:
9017 case RENDERPATH_D3D10:
9018 case RENDERPATH_D3D11:
9019 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9022 // TODO: do boxfilter scale-down in shader?
9023 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9024 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9025 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9027 // we now have a bloom image in the framebuffer
9028 // copy it into the bloom image texture for later processing
9029 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);
9030 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9033 void R_Bloom_CopyHDRTexture(void)
9035 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);
9036 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9039 void R_Bloom_MakeTexture(void)
9042 float xoffset, yoffset, r, brighten;
9044 r_refdef.stats.bloom++;
9046 R_ResetViewRendering2D();
9048 // we have a bloom image in the framebuffer
9050 R_SetViewport(&r_bloomstate.viewport);
9052 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9055 r = bound(0, r_bloom_colorexponent.value / x, 1);
9056 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9058 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9059 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9060 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9061 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9063 // copy the vertically blurred bloom view to a texture
9064 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);
9065 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9068 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9069 brighten = r_bloom_brighten.value;
9071 brighten *= r_hdr_range.value;
9072 brighten = sqrt(brighten);
9074 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9075 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9077 for (dir = 0;dir < 2;dir++)
9079 // blend on at multiple vertical offsets to achieve a vertical blur
9080 // TODO: do offset blends using GLSL
9081 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9082 GL_BlendFunc(GL_ONE, GL_ZERO);
9083 for (x = -range;x <= range;x++)
9085 if (!dir){xoffset = 0;yoffset = x;}
9086 else {xoffset = x;yoffset = 0;}
9087 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9088 yoffset /= (float)r_bloomstate.bloomtextureheight;
9089 // compute a texcoord array with the specified x and y offset
9090 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9091 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9092 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9093 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9094 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9095 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9096 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9097 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9098 // this r value looks like a 'dot' particle, fading sharply to
9099 // black at the edges
9100 // (probably not realistic but looks good enough)
9101 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9102 //r = brighten/(range*2+1);
9103 r = brighten / (range * 2 + 1);
9105 r *= (1 - x*x/(float)(range*range));
9106 GL_Color(r, r, r, 1);
9107 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9108 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9109 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9110 GL_BlendFunc(GL_ONE, GL_ONE);
9113 // copy the vertically blurred bloom view to a texture
9114 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);
9115 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9119 void R_HDR_RenderBloomTexture(void)
9121 int oldwidth, oldheight;
9122 float oldcolorscale;
9124 oldcolorscale = r_refdef.view.colorscale;
9125 oldwidth = r_refdef.view.width;
9126 oldheight = r_refdef.view.height;
9127 r_refdef.view.width = r_bloomstate.bloomwidth;
9128 r_refdef.view.height = r_bloomstate.bloomheight;
9130 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9131 // TODO: add exposure compensation features
9132 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9134 r_refdef.view.showdebug = false;
9135 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9137 R_ResetViewRendering3D();
9139 R_ClearScreen(r_refdef.fogenabled);
9140 if (r_timereport_active)
9141 R_TimeReport("HDRclear");
9144 if (r_timereport_active)
9145 R_TimeReport("visibility");
9147 // only do secondary renders with HDR if r_hdr is 2 or higher
9148 r_waterstate.numwaterplanes = 0;
9149 if (r_waterstate.enabled && r_hdr.integer >= 2)
9150 R_RenderWaterPlanes();
9152 r_refdef.view.showdebug = true;
9154 r_waterstate.numwaterplanes = 0;
9156 R_ResetViewRendering2D();
9158 R_Bloom_CopyHDRTexture();
9159 R_Bloom_MakeTexture();
9161 // restore the view settings
9162 r_refdef.view.width = oldwidth;
9163 r_refdef.view.height = oldheight;
9164 r_refdef.view.colorscale = oldcolorscale;
9166 R_ResetViewRendering3D();
9168 R_ClearScreen(r_refdef.fogenabled);
9169 if (r_timereport_active)
9170 R_TimeReport("viewclear");
9173 static void R_BlendView(void)
9175 unsigned int permutation;
9176 float uservecs[4][4];
9178 switch (vid.renderpath)
9180 case RENDERPATH_GL20:
9181 case RENDERPATH_CGGL:
9182 case RENDERPATH_D3D9:
9183 case RENDERPATH_D3D10:
9184 case RENDERPATH_D3D11:
9186 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9187 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9188 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9189 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9190 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9192 if (r_bloomstate.texture_screen)
9194 // make sure the buffer is available
9195 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9197 R_ResetViewRendering2D();
9199 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9201 // declare variables
9203 static float avgspeed;
9205 speed = VectorLength(cl.movement_velocity);
9207 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9208 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9210 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9211 speed = bound(0, speed, 1);
9212 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9214 // calculate values into a standard alpha
9215 cl.motionbluralpha = 1 - exp(-
9217 (r_motionblur.value * speed / 80)
9219 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9222 max(0.0001, cl.time - cl.oldtime) // fps independent
9225 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9226 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9228 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9230 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9231 GL_Color(1, 1, 1, cl.motionbluralpha);
9232 switch(vid.renderpath)
9234 case RENDERPATH_GL11:
9235 case RENDERPATH_GL13:
9236 case RENDERPATH_GL20:
9237 case RENDERPATH_CGGL:
9238 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9240 case RENDERPATH_D3D9:
9241 case RENDERPATH_D3D10:
9242 case RENDERPATH_D3D11:
9243 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9246 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9247 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9248 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9252 // copy view into the screen texture
9253 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);
9254 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9256 else if (!r_bloomstate.texture_bloom)
9258 // we may still have to do view tint...
9259 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9261 // apply a color tint to the whole view
9262 R_ResetViewRendering2D();
9263 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9264 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9265 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9266 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9267 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9269 break; // no screen processing, no bloom, skip it
9272 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9274 // render simple bloom effect
9275 // copy the screen and shrink it and darken it for the bloom process
9276 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9277 // make the bloom texture
9278 R_Bloom_MakeTexture();
9281 #if _MSC_VER >= 1400
9282 #define sscanf sscanf_s
9284 memset(uservecs, 0, sizeof(uservecs));
9285 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9286 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9287 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9288 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9290 R_ResetViewRendering2D();
9291 GL_Color(1, 1, 1, 1);
9292 GL_BlendFunc(GL_ONE, GL_ZERO);
9294 switch(vid.renderpath)
9296 case RENDERPATH_GL20:
9297 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9298 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9299 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9300 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9301 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9302 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]);
9303 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9304 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]);
9305 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]);
9306 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]);
9307 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]);
9308 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9309 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9310 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);
9312 case RENDERPATH_CGGL:
9314 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9315 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9316 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9317 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9318 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9319 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
9320 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9321 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
9322 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
9323 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
9324 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
9325 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9326 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9327 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);
9330 case RENDERPATH_D3D9:
9332 // 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...
9333 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9334 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9335 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9336 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9337 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9338 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9339 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9340 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9341 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9342 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9343 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9344 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9345 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9346 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9349 case RENDERPATH_D3D10:
9350 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9352 case RENDERPATH_D3D11:
9353 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9358 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9359 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9361 case RENDERPATH_GL13:
9362 case RENDERPATH_GL11:
9363 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9365 // apply a color tint to the whole view
9366 R_ResetViewRendering2D();
9367 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9368 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9369 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9370 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9371 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9377 matrix4x4_t r_waterscrollmatrix;
9379 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9381 if (r_refdef.fog_density)
9383 r_refdef.fogcolor[0] = r_refdef.fog_red;
9384 r_refdef.fogcolor[1] = r_refdef.fog_green;
9385 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9387 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9388 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9389 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9390 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9394 VectorCopy(r_refdef.fogcolor, fogvec);
9395 // color.rgb *= ContrastBoost * SceneBrightness;
9396 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9397 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9398 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9399 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9404 void R_UpdateVariables(void)
9408 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9410 r_refdef.farclip = r_farclip_base.value;
9411 if (r_refdef.scene.worldmodel)
9412 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9413 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9415 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9416 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9417 r_refdef.polygonfactor = 0;
9418 r_refdef.polygonoffset = 0;
9419 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9420 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9422 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9423 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9424 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9425 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9426 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9427 if (r_showsurfaces.integer)
9429 r_refdef.scene.rtworld = false;
9430 r_refdef.scene.rtworldshadows = false;
9431 r_refdef.scene.rtdlight = false;
9432 r_refdef.scene.rtdlightshadows = false;
9433 r_refdef.lightmapintensity = 0;
9436 if (gamemode == GAME_NEHAHRA)
9438 if (gl_fogenable.integer)
9440 r_refdef.oldgl_fogenable = true;
9441 r_refdef.fog_density = gl_fogdensity.value;
9442 r_refdef.fog_red = gl_fogred.value;
9443 r_refdef.fog_green = gl_foggreen.value;
9444 r_refdef.fog_blue = gl_fogblue.value;
9445 r_refdef.fog_alpha = 1;
9446 r_refdef.fog_start = 0;
9447 r_refdef.fog_end = gl_skyclip.value;
9448 r_refdef.fog_height = 1<<30;
9449 r_refdef.fog_fadedepth = 128;
9451 else if (r_refdef.oldgl_fogenable)
9453 r_refdef.oldgl_fogenable = false;
9454 r_refdef.fog_density = 0;
9455 r_refdef.fog_red = 0;
9456 r_refdef.fog_green = 0;
9457 r_refdef.fog_blue = 0;
9458 r_refdef.fog_alpha = 0;
9459 r_refdef.fog_start = 0;
9460 r_refdef.fog_end = 0;
9461 r_refdef.fog_height = 1<<30;
9462 r_refdef.fog_fadedepth = 128;
9466 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9467 r_refdef.fog_start = max(0, r_refdef.fog_start);
9468 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9470 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9472 if (r_refdef.fog_density && r_drawfog.integer)
9474 r_refdef.fogenabled = true;
9475 // this is the point where the fog reaches 0.9986 alpha, which we
9476 // consider a good enough cutoff point for the texture
9477 // (0.9986 * 256 == 255.6)
9478 if (r_fog_exp2.integer)
9479 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9481 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9482 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9483 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9484 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9485 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9486 R_BuildFogHeightTexture();
9487 // fog color was already set
9488 // update the fog texture
9489 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)
9490 R_BuildFogTexture();
9491 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9492 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9495 r_refdef.fogenabled = false;
9497 switch(vid.renderpath)
9499 case RENDERPATH_GL20:
9500 case RENDERPATH_CGGL:
9501 case RENDERPATH_D3D9:
9502 case RENDERPATH_D3D10:
9503 case RENDERPATH_D3D11:
9504 if(v_glslgamma.integer && !vid_gammatables_trivial)
9506 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9508 // build GLSL gamma texture
9509 #define RAMPWIDTH 256
9510 unsigned short ramp[RAMPWIDTH * 3];
9511 unsigned char rampbgr[RAMPWIDTH][4];
9514 r_texture_gammaramps_serial = vid_gammatables_serial;
9516 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9517 for(i = 0; i < RAMPWIDTH; ++i)
9519 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9520 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9521 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9524 if (r_texture_gammaramps)
9526 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9530 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9536 // remove GLSL gamma texture
9539 case RENDERPATH_GL13:
9540 case RENDERPATH_GL11:
9545 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9546 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9552 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9553 if( scenetype != r_currentscenetype ) {
9554 // store the old scenetype
9555 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9556 r_currentscenetype = scenetype;
9557 // move in the new scene
9558 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9567 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9569 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9570 if( scenetype == r_currentscenetype ) {
9571 return &r_refdef.scene;
9573 return &r_scenes_store[ scenetype ];
9582 void R_RenderView(void)
9584 if (r_timereport_active)
9585 R_TimeReport("start");
9586 r_textureframe++; // used only by R_GetCurrentTexture
9587 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9589 if (!r_drawentities.integer)
9590 r_refdef.scene.numentities = 0;
9592 R_AnimCache_ClearCache();
9593 R_FrameData_NewFrame();
9595 if (r_refdef.view.isoverlay)
9597 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9598 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9599 R_TimeReport("depthclear");
9601 r_refdef.view.showdebug = false;
9603 r_waterstate.enabled = false;
9604 r_waterstate.numwaterplanes = 0;
9612 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9613 return; //Host_Error ("R_RenderView: NULL worldmodel");
9615 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9617 R_RenderView_UpdateViewVectors();
9619 R_Shadow_UpdateWorldLightSelection();
9621 R_Bloom_StartFrame();
9622 R_Water_StartFrame();
9625 if (r_timereport_active)
9626 R_TimeReport("viewsetup");
9628 R_ResetViewRendering3D();
9630 if (r_refdef.view.clear || r_refdef.fogenabled)
9632 R_ClearScreen(r_refdef.fogenabled);
9633 if (r_timereport_active)
9634 R_TimeReport("viewclear");
9636 r_refdef.view.clear = true;
9638 // this produces a bloom texture to be used in R_BlendView() later
9639 if (r_hdr.integer && r_bloomstate.bloomwidth)
9641 R_HDR_RenderBloomTexture();
9642 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9643 r_textureframe++; // used only by R_GetCurrentTexture
9646 r_refdef.view.showdebug = true;
9649 if (r_timereport_active)
9650 R_TimeReport("visibility");
9652 r_waterstate.numwaterplanes = 0;
9653 if (r_waterstate.enabled)
9654 R_RenderWaterPlanes();
9657 r_waterstate.numwaterplanes = 0;
9660 if (r_timereport_active)
9661 R_TimeReport("blendview");
9663 GL_Scissor(0, 0, vid.width, vid.height);
9664 GL_ScissorTest(false);
9668 void R_RenderWaterPlanes(void)
9670 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9672 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9673 if (r_timereport_active)
9674 R_TimeReport("waterworld");
9677 // don't let sound skip if going slow
9678 if (r_refdef.scene.extraupdate)
9681 R_DrawModelsAddWaterPlanes();
9682 if (r_timereport_active)
9683 R_TimeReport("watermodels");
9685 if (r_waterstate.numwaterplanes)
9687 R_Water_ProcessPlanes();
9688 if (r_timereport_active)
9689 R_TimeReport("waterscenes");
9693 extern void R_DrawLightningBeams (void);
9694 extern void VM_CL_AddPolygonsToMeshQueue (void);
9695 extern void R_DrawPortals (void);
9696 extern cvar_t cl_locs_show;
9697 static void R_DrawLocs(void);
9698 static void R_DrawEntityBBoxes(void);
9699 static void R_DrawModelDecals(void);
9700 extern void R_DrawModelShadows(void);
9701 extern void R_DrawModelShadowMaps(void);
9702 extern cvar_t cl_decals_newsystem;
9703 extern qboolean r_shadow_usingdeferredprepass;
9704 void R_RenderScene(void)
9706 qboolean shadowmapping = false;
9708 if (r_timereport_active)
9709 R_TimeReport("beginscene");
9711 r_refdef.stats.renders++;
9715 // don't let sound skip if going slow
9716 if (r_refdef.scene.extraupdate)
9719 R_MeshQueue_BeginScene();
9723 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);
9725 if (r_timereport_active)
9726 R_TimeReport("skystartframe");
9728 if (cl.csqc_vidvars.drawworld)
9730 // don't let sound skip if going slow
9731 if (r_refdef.scene.extraupdate)
9734 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9736 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9737 if (r_timereport_active)
9738 R_TimeReport("worldsky");
9741 if (R_DrawBrushModelsSky() && r_timereport_active)
9742 R_TimeReport("bmodelsky");
9744 if (skyrendermasked && skyrenderlater)
9746 // we have to force off the water clipping plane while rendering sky
9750 if (r_timereport_active)
9751 R_TimeReport("sky");
9755 R_AnimCache_CacheVisibleEntities();
9756 if (r_timereport_active)
9757 R_TimeReport("animation");
9759 R_Shadow_PrepareLights();
9760 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9761 R_Shadow_PrepareModelShadows();
9762 if (r_timereport_active)
9763 R_TimeReport("preparelights");
9765 if (R_Shadow_ShadowMappingEnabled())
9766 shadowmapping = true;
9768 if (r_shadow_usingdeferredprepass)
9769 R_Shadow_DrawPrepass();
9771 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9773 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9774 if (r_timereport_active)
9775 R_TimeReport("worlddepth");
9777 if (r_depthfirst.integer >= 2)
9779 R_DrawModelsDepth();
9780 if (r_timereport_active)
9781 R_TimeReport("modeldepth");
9784 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9786 R_DrawModelShadowMaps();
9787 R_ResetViewRendering3D();
9788 // don't let sound skip if going slow
9789 if (r_refdef.scene.extraupdate)
9793 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9795 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9796 if (r_timereport_active)
9797 R_TimeReport("world");
9800 // don't let sound skip if going slow
9801 if (r_refdef.scene.extraupdate)
9805 if (r_timereport_active)
9806 R_TimeReport("models");
9808 // don't let sound skip if going slow
9809 if (r_refdef.scene.extraupdate)
9812 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9814 R_DrawModelShadows();
9815 R_ResetViewRendering3D();
9816 // don't let sound skip if going slow
9817 if (r_refdef.scene.extraupdate)
9821 if (!r_shadow_usingdeferredprepass)
9823 R_Shadow_DrawLights();
9824 if (r_timereport_active)
9825 R_TimeReport("rtlights");
9828 // don't let sound skip if going slow
9829 if (r_refdef.scene.extraupdate)
9832 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9834 R_DrawModelShadows();
9835 R_ResetViewRendering3D();
9836 // don't let sound skip if going slow
9837 if (r_refdef.scene.extraupdate)
9841 if (cl.csqc_vidvars.drawworld)
9843 if (cl_decals_newsystem.integer)
9845 R_DrawModelDecals();
9846 if (r_timereport_active)
9847 R_TimeReport("modeldecals");
9852 if (r_timereport_active)
9853 R_TimeReport("decals");
9857 if (r_timereport_active)
9858 R_TimeReport("particles");
9861 if (r_timereport_active)
9862 R_TimeReport("explosions");
9864 R_DrawLightningBeams();
9865 if (r_timereport_active)
9866 R_TimeReport("lightning");
9869 VM_CL_AddPolygonsToMeshQueue();
9871 if (r_refdef.view.showdebug)
9873 if (cl_locs_show.integer)
9876 if (r_timereport_active)
9877 R_TimeReport("showlocs");
9880 if (r_drawportals.integer)
9883 if (r_timereport_active)
9884 R_TimeReport("portals");
9887 if (r_showbboxes.value > 0)
9889 R_DrawEntityBBoxes();
9890 if (r_timereport_active)
9891 R_TimeReport("bboxes");
9895 R_MeshQueue_RenderTransparent();
9896 if (r_timereport_active)
9897 R_TimeReport("drawtrans");
9899 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))
9901 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9902 if (r_timereport_active)
9903 R_TimeReport("worlddebug");
9904 R_DrawModelsDebug();
9905 if (r_timereport_active)
9906 R_TimeReport("modeldebug");
9909 if (cl.csqc_vidvars.drawworld)
9911 R_Shadow_DrawCoronas();
9912 if (r_timereport_active)
9913 R_TimeReport("coronas");
9916 // don't let sound skip if going slow
9917 if (r_refdef.scene.extraupdate)
9920 R_ResetViewRendering2D();
9923 static const unsigned short bboxelements[36] =
9933 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9936 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9938 RSurf_ActiveWorldEntity();
9940 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9941 GL_DepthMask(false);
9942 GL_DepthRange(0, 1);
9943 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9944 R_Mesh_ResetTextureState();
9946 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9947 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9948 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9949 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9950 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9951 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9952 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9953 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9954 R_FillColors(color4f, 8, cr, cg, cb, ca);
9955 if (r_refdef.fogenabled)
9957 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9959 f1 = RSurf_FogVertex(v);
9961 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9962 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9963 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9966 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9967 R_Mesh_ResetTextureState();
9968 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9969 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9972 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9976 prvm_edict_t *edict;
9977 prvm_prog_t *prog_save = prog;
9979 // this function draws bounding boxes of server entities
9983 GL_CullFace(GL_NONE);
9984 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9988 for (i = 0;i < numsurfaces;i++)
9990 edict = PRVM_EDICT_NUM(surfacelist[i]);
9991 switch ((int)edict->fields.server->solid)
9993 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9994 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9995 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9996 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9997 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9998 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10000 color[3] *= r_showbboxes.value;
10001 color[3] = bound(0, color[3], 1);
10002 GL_DepthTest(!r_showdisabledepthtest.integer);
10003 GL_CullFace(r_refdef.view.cullface_front);
10004 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10010 static void R_DrawEntityBBoxes(void)
10013 prvm_edict_t *edict;
10015 prvm_prog_t *prog_save = prog;
10017 // this function draws bounding boxes of server entities
10023 for (i = 0;i < prog->num_edicts;i++)
10025 edict = PRVM_EDICT_NUM(i);
10026 if (edict->priv.server->free)
10028 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10029 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10031 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10033 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10034 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10040 static const int nomodelelement3i[24] =
10052 static const unsigned short nomodelelement3s[24] =
10064 static const float nomodelvertex3f[6*3] =
10074 static const float nomodelcolor4f[6*4] =
10076 0.0f, 0.0f, 0.5f, 1.0f,
10077 0.0f, 0.0f, 0.5f, 1.0f,
10078 0.0f, 0.5f, 0.0f, 1.0f,
10079 0.0f, 0.5f, 0.0f, 1.0f,
10080 0.5f, 0.0f, 0.0f, 1.0f,
10081 0.5f, 0.0f, 0.0f, 1.0f
10084 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10088 float color4f[6*4];
10090 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);
10092 // this is only called once per entity so numsurfaces is always 1, and
10093 // surfacelist is always {0}, so this code does not handle batches
10095 if (rsurface.ent_flags & RENDER_ADDITIVE)
10097 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10098 GL_DepthMask(false);
10100 else if (rsurface.colormod[3] < 1)
10102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10103 GL_DepthMask(false);
10107 GL_BlendFunc(GL_ONE, GL_ZERO);
10108 GL_DepthMask(true);
10110 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10111 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10112 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10113 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10114 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10115 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10116 for (i = 0, c = color4f;i < 6;i++, c += 4)
10118 c[0] *= rsurface.colormod[0];
10119 c[1] *= rsurface.colormod[1];
10120 c[2] *= rsurface.colormod[2];
10121 c[3] *= rsurface.colormod[3];
10123 if (r_refdef.fogenabled)
10125 for (i = 0, c = color4f;i < 6;i++, c += 4)
10127 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10129 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10130 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10131 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10134 R_Mesh_ResetTextureState();
10135 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10136 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10139 void R_DrawNoModel(entity_render_t *ent)
10142 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10143 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10144 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10146 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10149 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10151 vec3_t right1, right2, diff, normal;
10153 VectorSubtract (org2, org1, normal);
10155 // calculate 'right' vector for start
10156 VectorSubtract (r_refdef.view.origin, org1, diff);
10157 CrossProduct (normal, diff, right1);
10158 VectorNormalize (right1);
10160 // calculate 'right' vector for end
10161 VectorSubtract (r_refdef.view.origin, org2, diff);
10162 CrossProduct (normal, diff, right2);
10163 VectorNormalize (right2);
10165 vert[ 0] = org1[0] + width * right1[0];
10166 vert[ 1] = org1[1] + width * right1[1];
10167 vert[ 2] = org1[2] + width * right1[2];
10168 vert[ 3] = org1[0] - width * right1[0];
10169 vert[ 4] = org1[1] - width * right1[1];
10170 vert[ 5] = org1[2] - width * right1[2];
10171 vert[ 6] = org2[0] - width * right2[0];
10172 vert[ 7] = org2[1] - width * right2[1];
10173 vert[ 8] = org2[2] - width * right2[2];
10174 vert[ 9] = org2[0] + width * right2[0];
10175 vert[10] = org2[1] + width * right2[1];
10176 vert[11] = org2[2] + width * right2[2];
10179 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)
10181 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10182 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10183 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10184 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10185 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10186 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10187 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10188 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10189 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10190 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10191 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10192 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10195 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10200 VectorSet(v, x, y, z);
10201 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10202 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10204 if (i == mesh->numvertices)
10206 if (mesh->numvertices < mesh->maxvertices)
10208 VectorCopy(v, vertex3f);
10209 mesh->numvertices++;
10211 return mesh->numvertices;
10217 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10220 int *e, element[3];
10221 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10222 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10223 e = mesh->element3i + mesh->numtriangles * 3;
10224 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10226 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10227 if (mesh->numtriangles < mesh->maxtriangles)
10232 mesh->numtriangles++;
10234 element[1] = element[2];
10238 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10241 int *e, element[3];
10242 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10243 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10244 e = mesh->element3i + mesh->numtriangles * 3;
10245 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10247 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10248 if (mesh->numtriangles < mesh->maxtriangles)
10253 mesh->numtriangles++;
10255 element[1] = element[2];
10259 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10260 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10262 int planenum, planenum2;
10265 mplane_t *plane, *plane2;
10267 double temppoints[2][256*3];
10268 // figure out how large a bounding box we need to properly compute this brush
10270 for (w = 0;w < numplanes;w++)
10271 maxdist = max(maxdist, fabs(planes[w].dist));
10272 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10273 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10274 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10278 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10279 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10281 if (planenum2 == planenum)
10283 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);
10286 if (tempnumpoints < 3)
10288 // generate elements forming a triangle fan for this polygon
10289 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10293 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)
10295 texturelayer_t *layer;
10296 layer = t->currentlayers + t->currentnumlayers++;
10297 layer->type = type;
10298 layer->depthmask = depthmask;
10299 layer->blendfunc1 = blendfunc1;
10300 layer->blendfunc2 = blendfunc2;
10301 layer->texture = texture;
10302 layer->texmatrix = *matrix;
10303 layer->color[0] = r;
10304 layer->color[1] = g;
10305 layer->color[2] = b;
10306 layer->color[3] = a;
10309 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10311 if(parms[0] == 0 && parms[1] == 0)
10313 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10314 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10319 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10322 index = parms[2] + r_refdef.scene.time * parms[3];
10323 index -= floor(index);
10324 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10327 case Q3WAVEFUNC_NONE:
10328 case Q3WAVEFUNC_NOISE:
10329 case Q3WAVEFUNC_COUNT:
10332 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10333 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10334 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10335 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10336 case Q3WAVEFUNC_TRIANGLE:
10338 f = index - floor(index);
10341 else if (index < 2)
10343 else if (index < 3)
10349 f = parms[0] + parms[1] * f;
10350 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10351 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10355 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10360 matrix4x4_t matrix, temp;
10361 switch(tcmod->tcmod)
10363 case Q3TCMOD_COUNT:
10365 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10366 matrix = r_waterscrollmatrix;
10368 matrix = identitymatrix;
10370 case Q3TCMOD_ENTITYTRANSLATE:
10371 // this is used in Q3 to allow the gamecode to control texcoord
10372 // scrolling on the entity, which is not supported in darkplaces yet.
10373 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10375 case Q3TCMOD_ROTATE:
10376 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10377 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10378 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10380 case Q3TCMOD_SCALE:
10381 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10383 case Q3TCMOD_SCROLL:
10384 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10386 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10387 w = (int) tcmod->parms[0];
10388 h = (int) tcmod->parms[1];
10389 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10391 idx = (int) floor(f * w * h);
10392 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10394 case Q3TCMOD_STRETCH:
10395 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10396 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10398 case Q3TCMOD_TRANSFORM:
10399 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10400 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10401 VectorSet(tcmat + 6, 0 , 0 , 1);
10402 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10403 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10405 case Q3TCMOD_TURBULENT:
10406 // this is handled in the RSurf_PrepareVertices function
10407 matrix = identitymatrix;
10411 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10414 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10416 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10417 char name[MAX_QPATH];
10418 skinframe_t *skinframe;
10419 unsigned char pixels[296*194];
10420 strlcpy(cache->name, skinname, sizeof(cache->name));
10421 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10422 if (developer_loading.integer)
10423 Con_Printf("loading %s\n", name);
10424 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10425 if (!skinframe || !skinframe->base)
10428 fs_offset_t filesize;
10430 f = FS_LoadFile(name, tempmempool, true, &filesize);
10433 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10434 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10438 cache->skinframe = skinframe;
10441 texture_t *R_GetCurrentTexture(texture_t *t)
10444 const entity_render_t *ent = rsurface.entity;
10445 dp_model_t *model = ent->model;
10446 q3shaderinfo_layer_tcmod_t *tcmod;
10448 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10449 return t->currentframe;
10450 t->update_lastrenderframe = r_textureframe;
10451 t->update_lastrenderentity = (void *)ent;
10453 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10454 t->camera_entity = ent->entitynumber;
10456 t->camera_entity = 0;
10458 // switch to an alternate material if this is a q1bsp animated material
10460 texture_t *texture = t;
10461 int s = rsurface.ent_skinnum;
10462 if ((unsigned int)s >= (unsigned int)model->numskins)
10464 if (model->skinscenes)
10466 if (model->skinscenes[s].framecount > 1)
10467 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10469 s = model->skinscenes[s].firstframe;
10472 t = t + s * model->num_surfaces;
10475 // use an alternate animation if the entity's frame is not 0,
10476 // and only if the texture has an alternate animation
10477 if (rsurface.ent_alttextures && t->anim_total[1])
10478 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10480 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10482 texture->currentframe = t;
10485 // update currentskinframe to be a qw skin or animation frame
10486 if (rsurface.ent_qwskin >= 0)
10488 i = rsurface.ent_qwskin;
10489 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10491 r_qwskincache_size = cl.maxclients;
10493 Mem_Free(r_qwskincache);
10494 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10496 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10497 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10498 t->currentskinframe = r_qwskincache[i].skinframe;
10499 if (t->currentskinframe == NULL)
10500 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10502 else if (t->numskinframes >= 2)
10503 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10504 if (t->backgroundnumskinframes >= 2)
10505 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10507 t->currentmaterialflags = t->basematerialflags;
10508 t->currentalpha = rsurface.colormod[3];
10509 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10510 t->currentalpha *= r_wateralpha.value;
10511 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10512 t->currentalpha *= t->r_water_wateralpha;
10513 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10514 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10515 if (!(rsurface.ent_flags & RENDER_LIGHT))
10516 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10517 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10519 // pick a model lighting mode
10520 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10521 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10523 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10525 if (rsurface.ent_flags & RENDER_ADDITIVE)
10526 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10527 else if (t->currentalpha < 1)
10528 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10529 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10530 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10531 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10532 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10533 if (t->backgroundnumskinframes)
10534 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10535 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10537 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10538 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10541 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10542 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10543 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10545 // there is no tcmod
10546 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10548 t->currenttexmatrix = r_waterscrollmatrix;
10549 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10551 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10553 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10554 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10557 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10558 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10559 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10560 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10562 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10563 if (t->currentskinframe->qpixels)
10564 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10565 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10566 if (!t->basetexture)
10567 t->basetexture = r_texture_notexture;
10568 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10569 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10570 t->nmaptexture = t->currentskinframe->nmap;
10571 if (!t->nmaptexture)
10572 t->nmaptexture = r_texture_blanknormalmap;
10573 t->glosstexture = r_texture_black;
10574 t->glowtexture = t->currentskinframe->glow;
10575 t->fogtexture = t->currentskinframe->fog;
10576 t->reflectmasktexture = t->currentskinframe->reflect;
10577 if (t->backgroundnumskinframes)
10579 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10580 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10581 t->backgroundglosstexture = r_texture_black;
10582 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10583 if (!t->backgroundnmaptexture)
10584 t->backgroundnmaptexture = r_texture_blanknormalmap;
10588 t->backgroundbasetexture = r_texture_white;
10589 t->backgroundnmaptexture = r_texture_blanknormalmap;
10590 t->backgroundglosstexture = r_texture_black;
10591 t->backgroundglowtexture = NULL;
10593 t->specularpower = r_shadow_glossexponent.value;
10594 // TODO: store reference values for these in the texture?
10595 t->specularscale = 0;
10596 if (r_shadow_gloss.integer > 0)
10598 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10600 if (r_shadow_glossintensity.value > 0)
10602 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10603 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10604 t->specularscale = r_shadow_glossintensity.value;
10607 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10609 t->glosstexture = r_texture_white;
10610 t->backgroundglosstexture = r_texture_white;
10611 t->specularscale = r_shadow_gloss2intensity.value;
10612 t->specularpower = r_shadow_gloss2exponent.value;
10615 t->specularscale *= t->specularscalemod;
10616 t->specularpower *= t->specularpowermod;
10618 // lightmaps mode looks bad with dlights using actual texturing, so turn
10619 // off the colormap and glossmap, but leave the normalmap on as it still
10620 // accurately represents the shading involved
10621 if (gl_lightmaps.integer)
10623 t->basetexture = r_texture_grey128;
10624 t->pantstexture = r_texture_black;
10625 t->shirttexture = r_texture_black;
10626 t->nmaptexture = r_texture_blanknormalmap;
10627 t->glosstexture = r_texture_black;
10628 t->glowtexture = NULL;
10629 t->fogtexture = NULL;
10630 t->reflectmasktexture = NULL;
10631 t->backgroundbasetexture = NULL;
10632 t->backgroundnmaptexture = r_texture_blanknormalmap;
10633 t->backgroundglosstexture = r_texture_black;
10634 t->backgroundglowtexture = NULL;
10635 t->specularscale = 0;
10636 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10639 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10640 VectorClear(t->dlightcolor);
10641 t->currentnumlayers = 0;
10642 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10644 int blendfunc1, blendfunc2;
10645 qboolean depthmask;
10646 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10648 blendfunc1 = GL_SRC_ALPHA;
10649 blendfunc2 = GL_ONE;
10651 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10653 blendfunc1 = GL_SRC_ALPHA;
10654 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10656 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10658 blendfunc1 = t->customblendfunc[0];
10659 blendfunc2 = t->customblendfunc[1];
10663 blendfunc1 = GL_ONE;
10664 blendfunc2 = GL_ZERO;
10666 // don't colormod evilblend textures
10667 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10668 VectorSet(t->lightmapcolor, 1, 1, 1);
10669 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10670 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10672 // fullbright is not affected by r_refdef.lightmapintensity
10673 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]);
10674 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10675 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]);
10676 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10677 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]);
10681 vec3_t ambientcolor;
10683 // set the color tint used for lights affecting this surface
10684 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10686 // q3bsp has no lightmap updates, so the lightstylevalue that
10687 // would normally be baked into the lightmap must be
10688 // applied to the color
10689 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10690 if (model->type == mod_brushq3)
10691 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10692 colorscale *= r_refdef.lightmapintensity;
10693 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10694 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10695 // basic lit geometry
10696 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]);
10697 // add pants/shirt if needed
10698 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10699 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]);
10700 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10701 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]);
10702 // now add ambient passes if needed
10703 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10705 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]);
10706 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10707 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]);
10708 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10709 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]);
10712 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10713 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]);
10714 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10716 // if this is opaque use alpha blend which will darken the earlier
10719 // if this is an alpha blended material, all the earlier passes
10720 // were darkened by fog already, so we only need to add the fog
10721 // color ontop through the fog mask texture
10723 // if this is an additive blended material, all the earlier passes
10724 // were darkened by fog already, and we should not add fog color
10725 // (because the background was not darkened, there is no fog color
10726 // that was lost behind it).
10727 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]);
10731 return t->currentframe;
10734 rsurfacestate_t rsurface;
10736 void R_Mesh_ResizeArrays(int newvertices)
10738 unsigned char *base;
10740 if (rsurface.array_size >= newvertices)
10742 if (rsurface.array_base)
10743 Mem_Free(rsurface.array_base);
10744 rsurface.array_size = (newvertices + 1023) & ~1023;
10746 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10747 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10748 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10749 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10750 size += rsurface.array_size * sizeof(float[3]);
10751 size += rsurface.array_size * sizeof(float[3]);
10752 size += rsurface.array_size * sizeof(float[3]);
10753 size += rsurface.array_size * sizeof(float[3]);
10754 size += rsurface.array_size * sizeof(float[3]);
10755 size += rsurface.array_size * sizeof(float[3]);
10756 size += rsurface.array_size * sizeof(float[3]);
10757 size += rsurface.array_size * sizeof(float[3]);
10758 size += rsurface.array_size * sizeof(float[4]);
10759 size += rsurface.array_size * sizeof(float[2]);
10760 size += rsurface.array_size * sizeof(float[2]);
10761 size += rsurface.array_size * sizeof(float[4]);
10762 size += rsurface.array_size * sizeof(int[3]);
10763 size += rsurface.array_size * sizeof(unsigned short[3]);
10764 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10765 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10766 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10767 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10768 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10769 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10770 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10771 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10772 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10773 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10774 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10775 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10776 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10777 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10778 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10779 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10780 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10781 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10782 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10785 void RSurf_ActiveWorldEntity(void)
10787 dp_model_t *model = r_refdef.scene.worldmodel;
10788 //if (rsurface.entity == r_refdef.scene.worldentity)
10790 rsurface.entity = r_refdef.scene.worldentity;
10791 rsurface.skeleton = NULL;
10792 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10793 rsurface.ent_skinnum = 0;
10794 rsurface.ent_qwskin = -1;
10795 rsurface.ent_shadertime = 0;
10796 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10797 if (rsurface.array_size < model->surfmesh.num_vertices)
10798 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10799 rsurface.matrix = identitymatrix;
10800 rsurface.inversematrix = identitymatrix;
10801 rsurface.matrixscale = 1;
10802 rsurface.inversematrixscale = 1;
10803 R_EntityMatrix(&identitymatrix);
10804 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10805 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10806 rsurface.fograngerecip = r_refdef.fograngerecip;
10807 rsurface.fogheightfade = r_refdef.fogheightfade;
10808 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10809 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10810 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10811 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10812 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10813 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10814 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10815 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10816 rsurface.colormod[3] = 1;
10817 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);
10818 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10819 rsurface.frameblend[0].lerp = 1;
10820 rsurface.ent_alttextures = false;
10821 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10822 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10823 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10824 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10825 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10826 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10827 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10828 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10829 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10830 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10831 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10832 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10833 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10834 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10835 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10836 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10837 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10838 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10839 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10840 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10841 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10842 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10843 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10844 rsurface.modelelement3i = model->surfmesh.data_element3i;
10845 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10846 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10847 rsurface.modelelement3s = model->surfmesh.data_element3s;
10848 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10849 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10850 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10851 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10852 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10853 rsurface.modelsurfaces = model->data_surfaces;
10854 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10855 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10856 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10857 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10858 rsurface.modelgeneratedvertex = false;
10859 rsurface.batchgeneratedvertex = false;
10860 rsurface.batchfirstvertex = 0;
10861 rsurface.batchnumvertices = 0;
10862 rsurface.batchfirsttriangle = 0;
10863 rsurface.batchnumtriangles = 0;
10864 rsurface.batchvertex3f = NULL;
10865 rsurface.batchvertex3f_vertexbuffer = NULL;
10866 rsurface.batchvertex3f_bufferoffset = 0;
10867 rsurface.batchsvector3f = NULL;
10868 rsurface.batchsvector3f_vertexbuffer = NULL;
10869 rsurface.batchsvector3f_bufferoffset = 0;
10870 rsurface.batchtvector3f = NULL;
10871 rsurface.batchtvector3f_vertexbuffer = NULL;
10872 rsurface.batchtvector3f_bufferoffset = 0;
10873 rsurface.batchnormal3f = NULL;
10874 rsurface.batchnormal3f_vertexbuffer = NULL;
10875 rsurface.batchnormal3f_bufferoffset = 0;
10876 rsurface.batchlightmapcolor4f = NULL;
10877 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10878 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10879 rsurface.batchtexcoordtexture2f = NULL;
10880 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10881 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10882 rsurface.batchtexcoordlightmap2f = NULL;
10883 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10884 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10885 rsurface.batchvertexmesh = NULL;
10886 rsurface.batchvertexmeshbuffer = NULL;
10887 rsurface.batchvertexposition = NULL;
10888 rsurface.batchvertexpositionbuffer = NULL;
10889 rsurface.batchelement3i = NULL;
10890 rsurface.batchelement3i_indexbuffer = NULL;
10891 rsurface.batchelement3i_bufferoffset = 0;
10892 rsurface.batchelement3s = NULL;
10893 rsurface.batchelement3s_indexbuffer = NULL;
10894 rsurface.batchelement3s_bufferoffset = 0;
10895 rsurface.passcolor4f = NULL;
10896 rsurface.passcolor4f_vertexbuffer = NULL;
10897 rsurface.passcolor4f_bufferoffset = 0;
10900 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10902 dp_model_t *model = ent->model;
10903 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10905 rsurface.entity = (entity_render_t *)ent;
10906 rsurface.skeleton = ent->skeleton;
10907 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10908 rsurface.ent_skinnum = ent->skinnum;
10909 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;
10910 rsurface.ent_shadertime = ent->shadertime;
10911 rsurface.ent_flags = ent->flags;
10912 if (rsurface.array_size < model->surfmesh.num_vertices)
10913 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10914 rsurface.matrix = ent->matrix;
10915 rsurface.inversematrix = ent->inversematrix;
10916 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10917 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10918 R_EntityMatrix(&rsurface.matrix);
10919 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10920 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10921 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10922 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10923 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10924 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10925 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10926 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10927 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10928 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10929 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10930 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10931 rsurface.colormod[3] = ent->alpha;
10932 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10933 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10934 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10935 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10936 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10937 if (ent->model->brush.submodel && !prepass)
10939 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10940 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10942 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10944 if (ent->animcache_vertex3f && !r_framedata_failed)
10946 rsurface.modelvertex3f = ent->animcache_vertex3f;
10947 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10948 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10949 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10950 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10951 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10952 rsurface.modelvertexposition = ent->animcache_vertexposition;
10953 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10955 else if (wanttangents)
10957 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10958 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10959 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10960 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10961 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10962 rsurface.modelvertexmesh = NULL;
10963 rsurface.modelvertexmeshbuffer = NULL;
10964 rsurface.modelvertexposition = NULL;
10965 rsurface.modelvertexpositionbuffer = NULL;
10967 else if (wantnormals)
10969 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10970 rsurface.modelsvector3f = NULL;
10971 rsurface.modeltvector3f = NULL;
10972 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10973 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10974 rsurface.modelvertexmesh = NULL;
10975 rsurface.modelvertexmeshbuffer = NULL;
10976 rsurface.modelvertexposition = NULL;
10977 rsurface.modelvertexpositionbuffer = NULL;
10981 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10982 rsurface.modelsvector3f = NULL;
10983 rsurface.modeltvector3f = NULL;
10984 rsurface.modelnormal3f = NULL;
10985 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10986 rsurface.modelvertexmesh = NULL;
10987 rsurface.modelvertexmeshbuffer = NULL;
10988 rsurface.modelvertexposition = NULL;
10989 rsurface.modelvertexpositionbuffer = NULL;
10991 rsurface.modelvertex3f_vertexbuffer = 0;
10992 rsurface.modelvertex3f_bufferoffset = 0;
10993 rsurface.modelsvector3f_vertexbuffer = 0;
10994 rsurface.modelsvector3f_bufferoffset = 0;
10995 rsurface.modeltvector3f_vertexbuffer = 0;
10996 rsurface.modeltvector3f_bufferoffset = 0;
10997 rsurface.modelnormal3f_vertexbuffer = 0;
10998 rsurface.modelnormal3f_bufferoffset = 0;
10999 rsurface.modelgeneratedvertex = true;
11003 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11004 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11005 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11006 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11007 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11008 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11009 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11010 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11011 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11012 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11013 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11014 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11015 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11016 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11017 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11018 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11019 rsurface.modelgeneratedvertex = false;
11021 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11022 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11023 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11024 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11025 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11026 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11027 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11028 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11029 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11030 rsurface.modelelement3i = model->surfmesh.data_element3i;
11031 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11032 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11033 rsurface.modelelement3s = model->surfmesh.data_element3s;
11034 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11035 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11036 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11037 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11038 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11039 rsurface.modelsurfaces = model->data_surfaces;
11040 rsurface.batchgeneratedvertex = false;
11041 rsurface.batchfirstvertex = 0;
11042 rsurface.batchnumvertices = 0;
11043 rsurface.batchfirsttriangle = 0;
11044 rsurface.batchnumtriangles = 0;
11045 rsurface.batchvertex3f = NULL;
11046 rsurface.batchvertex3f_vertexbuffer = NULL;
11047 rsurface.batchvertex3f_bufferoffset = 0;
11048 rsurface.batchsvector3f = NULL;
11049 rsurface.batchsvector3f_vertexbuffer = NULL;
11050 rsurface.batchsvector3f_bufferoffset = 0;
11051 rsurface.batchtvector3f = NULL;
11052 rsurface.batchtvector3f_vertexbuffer = NULL;
11053 rsurface.batchtvector3f_bufferoffset = 0;
11054 rsurface.batchnormal3f = NULL;
11055 rsurface.batchnormal3f_vertexbuffer = NULL;
11056 rsurface.batchnormal3f_bufferoffset = 0;
11057 rsurface.batchlightmapcolor4f = NULL;
11058 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11059 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11060 rsurface.batchtexcoordtexture2f = NULL;
11061 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11062 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11063 rsurface.batchtexcoordlightmap2f = NULL;
11064 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11065 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11066 rsurface.batchvertexmesh = NULL;
11067 rsurface.batchvertexmeshbuffer = NULL;
11068 rsurface.batchvertexposition = NULL;
11069 rsurface.batchvertexpositionbuffer = NULL;
11070 rsurface.batchelement3i = NULL;
11071 rsurface.batchelement3i_indexbuffer = NULL;
11072 rsurface.batchelement3i_bufferoffset = 0;
11073 rsurface.batchelement3s = NULL;
11074 rsurface.batchelement3s_indexbuffer = NULL;
11075 rsurface.batchelement3s_bufferoffset = 0;
11076 rsurface.passcolor4f = NULL;
11077 rsurface.passcolor4f_vertexbuffer = NULL;
11078 rsurface.passcolor4f_bufferoffset = 0;
11081 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)
11085 rsurface.entity = r_refdef.scene.worldentity;
11086 rsurface.skeleton = NULL;
11087 rsurface.ent_skinnum = 0;
11088 rsurface.ent_qwskin = -1;
11089 rsurface.ent_shadertime = shadertime;
11090 rsurface.ent_flags = entflags;
11091 rsurface.modelnumvertices = numvertices;
11092 rsurface.modelnumtriangles = numtriangles;
11093 if (rsurface.array_size < rsurface.modelnumvertices)
11094 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11095 rsurface.matrix = *matrix;
11096 rsurface.inversematrix = *inversematrix;
11097 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11098 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11099 R_EntityMatrix(&rsurface.matrix);
11100 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11101 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11102 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11103 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11104 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11105 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11106 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11107 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11108 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11109 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11110 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11111 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11112 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);
11113 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11114 rsurface.frameblend[0].lerp = 1;
11115 rsurface.ent_alttextures = false;
11116 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11117 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11120 rsurface.modelvertex3f = vertex3f;
11121 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11122 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11123 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11125 else if (wantnormals)
11127 rsurface.modelvertex3f = vertex3f;
11128 rsurface.modelsvector3f = NULL;
11129 rsurface.modeltvector3f = NULL;
11130 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11134 rsurface.modelvertex3f = vertex3f;
11135 rsurface.modelsvector3f = NULL;
11136 rsurface.modeltvector3f = NULL;
11137 rsurface.modelnormal3f = NULL;
11139 rsurface.modelvertexmesh = NULL;
11140 rsurface.modelvertexmeshbuffer = NULL;
11141 rsurface.modelvertexposition = NULL;
11142 rsurface.modelvertexpositionbuffer = NULL;
11143 rsurface.modelvertex3f_vertexbuffer = 0;
11144 rsurface.modelvertex3f_bufferoffset = 0;
11145 rsurface.modelsvector3f_vertexbuffer = 0;
11146 rsurface.modelsvector3f_bufferoffset = 0;
11147 rsurface.modeltvector3f_vertexbuffer = 0;
11148 rsurface.modeltvector3f_bufferoffset = 0;
11149 rsurface.modelnormal3f_vertexbuffer = 0;
11150 rsurface.modelnormal3f_bufferoffset = 0;
11151 rsurface.modelgeneratedvertex = true;
11152 rsurface.modellightmapcolor4f = color4f;
11153 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11154 rsurface.modellightmapcolor4f_bufferoffset = 0;
11155 rsurface.modeltexcoordtexture2f = texcoord2f;
11156 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11157 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11158 rsurface.modeltexcoordlightmap2f = NULL;
11159 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11160 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11161 rsurface.modelelement3i = element3i;
11162 rsurface.modelelement3i_indexbuffer = NULL;
11163 rsurface.modelelement3i_bufferoffset = 0;
11164 rsurface.modelelement3s = element3s;
11165 rsurface.modelelement3s_indexbuffer = NULL;
11166 rsurface.modelelement3s_bufferoffset = 0;
11167 rsurface.modellightmapoffsets = NULL;
11168 rsurface.modelsurfaces = NULL;
11169 rsurface.batchgeneratedvertex = false;
11170 rsurface.batchfirstvertex = 0;
11171 rsurface.batchnumvertices = 0;
11172 rsurface.batchfirsttriangle = 0;
11173 rsurface.batchnumtriangles = 0;
11174 rsurface.batchvertex3f = NULL;
11175 rsurface.batchvertex3f_vertexbuffer = NULL;
11176 rsurface.batchvertex3f_bufferoffset = 0;
11177 rsurface.batchsvector3f = NULL;
11178 rsurface.batchsvector3f_vertexbuffer = NULL;
11179 rsurface.batchsvector3f_bufferoffset = 0;
11180 rsurface.batchtvector3f = NULL;
11181 rsurface.batchtvector3f_vertexbuffer = NULL;
11182 rsurface.batchtvector3f_bufferoffset = 0;
11183 rsurface.batchnormal3f = NULL;
11184 rsurface.batchnormal3f_vertexbuffer = NULL;
11185 rsurface.batchnormal3f_bufferoffset = 0;
11186 rsurface.batchlightmapcolor4f = NULL;
11187 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11188 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11189 rsurface.batchtexcoordtexture2f = NULL;
11190 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11191 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11192 rsurface.batchtexcoordlightmap2f = NULL;
11193 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11194 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11195 rsurface.batchvertexmesh = NULL;
11196 rsurface.batchvertexmeshbuffer = NULL;
11197 rsurface.batchvertexposition = NULL;
11198 rsurface.batchvertexpositionbuffer = NULL;
11199 rsurface.batchelement3i = NULL;
11200 rsurface.batchelement3i_indexbuffer = NULL;
11201 rsurface.batchelement3i_bufferoffset = 0;
11202 rsurface.batchelement3s = NULL;
11203 rsurface.batchelement3s_indexbuffer = NULL;
11204 rsurface.batchelement3s_bufferoffset = 0;
11205 rsurface.passcolor4f = NULL;
11206 rsurface.passcolor4f_vertexbuffer = NULL;
11207 rsurface.passcolor4f_bufferoffset = 0;
11209 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11211 if ((wantnormals || wanttangents) && !normal3f)
11213 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11214 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11216 if (wanttangents && !svector3f)
11218 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);
11219 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11220 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11224 // now convert arrays into vertexmesh structs
11225 for (i = 0;i < numvertices;i++)
11227 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11228 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11229 if (rsurface.modelsvector3f)
11230 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11231 if (rsurface.modeltvector3f)
11232 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11233 if (rsurface.modelnormal3f)
11234 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11235 if (rsurface.modellightmapcolor4f)
11236 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11237 if (rsurface.modeltexcoordtexture2f)
11238 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11239 if (rsurface.modeltexcoordlightmap2f)
11240 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11244 float RSurf_FogPoint(const float *v)
11246 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11247 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11248 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11249 float FogHeightFade = r_refdef.fogheightfade;
11251 unsigned int fogmasktableindex;
11252 if (r_refdef.fogplaneviewabove)
11253 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11255 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11256 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11257 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11260 float RSurf_FogVertex(const float *v)
11262 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11263 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11264 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11265 float FogHeightFade = rsurface.fogheightfade;
11267 unsigned int fogmasktableindex;
11268 if (r_refdef.fogplaneviewabove)
11269 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11271 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11272 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11273 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11276 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11279 for (i = 0;i < numelements;i++)
11280 outelement3i[i] = inelement3i[i] + adjust;
11283 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11284 extern cvar_t gl_vbo;
11285 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11293 int surfacefirsttriangle;
11294 int surfacenumtriangles;
11295 int surfacefirstvertex;
11296 int surfaceendvertex;
11297 int surfacenumvertices;
11298 int surfaceadjustvertex;
11302 qboolean dynamicvertex;
11306 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11307 float waveparms[4];
11308 q3shaderinfo_deform_t *deform;
11309 const msurface_t *surface, *firstsurface;
11310 r_vertexposition_t *vertexposition;
11311 r_vertexmesh_t *vertexmesh;
11312 if (!texturenumsurfaces)
11314 // find vertex range of this surface batch
11316 firstsurface = texturesurfacelist[0];
11317 firsttriangle = firstsurface->num_firsttriangle;
11319 firstvertex = endvertex = firstsurface->num_firstvertex;
11320 for (i = 0;i < texturenumsurfaces;i++)
11322 surface = texturesurfacelist[i];
11323 if (surface != firstsurface + i)
11325 surfacefirstvertex = surface->num_firstvertex;
11326 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11327 surfacenumtriangles = surface->num_triangles;
11328 if (firstvertex > surfacefirstvertex)
11329 firstvertex = surfacefirstvertex;
11330 if (endvertex < surfaceendvertex)
11331 endvertex = surfaceendvertex;
11332 numtriangles += surfacenumtriangles;
11337 // we now know the vertex range used, and if there are any gaps in it
11338 rsurface.batchfirstvertex = firstvertex;
11339 rsurface.batchnumvertices = endvertex - firstvertex;
11340 rsurface.batchfirsttriangle = firsttriangle;
11341 rsurface.batchnumtriangles = numtriangles;
11343 // this variable holds flags for which properties have been updated that
11344 // may require regenerating vertexmesh or vertexposition arrays...
11347 // check if any dynamic vertex processing must occur
11348 dynamicvertex = false;
11350 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11351 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11352 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11354 switch (deform->deform)
11357 case Q3DEFORM_PROJECTIONSHADOW:
11358 case Q3DEFORM_TEXT0:
11359 case Q3DEFORM_TEXT1:
11360 case Q3DEFORM_TEXT2:
11361 case Q3DEFORM_TEXT3:
11362 case Q3DEFORM_TEXT4:
11363 case Q3DEFORM_TEXT5:
11364 case Q3DEFORM_TEXT6:
11365 case Q3DEFORM_TEXT7:
11366 case Q3DEFORM_NONE:
11368 case Q3DEFORM_AUTOSPRITE:
11369 dynamicvertex = true;
11370 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11371 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11373 case Q3DEFORM_AUTOSPRITE2:
11374 dynamicvertex = true;
11375 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11376 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11378 case Q3DEFORM_NORMAL:
11379 dynamicvertex = true;
11380 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11381 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11383 case Q3DEFORM_WAVE:
11384 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11385 break; // if wavefunc is a nop, ignore this transform
11386 dynamicvertex = true;
11387 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11388 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11390 case Q3DEFORM_BULGE:
11391 dynamicvertex = true;
11392 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11393 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11395 case Q3DEFORM_MOVE:
11396 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11397 break; // if wavefunc is a nop, ignore this transform
11398 dynamicvertex = true;
11399 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11400 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11404 switch(rsurface.texture->tcgen.tcgen)
11407 case Q3TCGEN_TEXTURE:
11409 case Q3TCGEN_LIGHTMAP:
11410 dynamicvertex = true;
11411 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11412 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11414 case Q3TCGEN_VECTOR:
11415 dynamicvertex = true;
11416 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11417 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11419 case Q3TCGEN_ENVIRONMENT:
11420 dynamicvertex = true;
11421 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11422 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11425 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11427 dynamicvertex = true;
11428 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11429 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11432 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11434 dynamicvertex = true;
11435 batchneed |= BATCHNEED_NOGAPS;
11436 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11439 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11441 dynamicvertex = true;
11442 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11443 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11446 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11448 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11449 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11450 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11451 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11452 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11453 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11454 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11457 // when the model data has no vertex buffer (dynamic mesh), we need to
11459 if (!rsurface.modelvertexmeshbuffer)
11460 batchneed |= BATCHNEED_NOGAPS;
11462 // if needsupdate, we have to do a dynamic vertex batch for sure
11463 if (needsupdate & batchneed)
11464 dynamicvertex = true;
11466 // see if we need to build vertexmesh from arrays
11467 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11468 dynamicvertex = true;
11470 // see if we need to build vertexposition from arrays
11471 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11472 dynamicvertex = true;
11474 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11475 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11476 dynamicvertex = true;
11478 // if there is a chance of animated vertex colors, it's a dynamic batch
11479 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11480 dynamicvertex = true;
11482 rsurface.batchvertex3f = rsurface.modelvertex3f;
11483 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11484 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11485 rsurface.batchsvector3f = rsurface.modelsvector3f;
11486 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11487 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11488 rsurface.batchtvector3f = rsurface.modeltvector3f;
11489 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11490 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11491 rsurface.batchnormal3f = rsurface.modelnormal3f;
11492 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11493 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11494 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11495 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11496 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11497 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11498 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11499 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11500 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11501 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11502 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11503 rsurface.batchvertexposition = rsurface.modelvertexposition;
11504 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11505 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11506 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11507 rsurface.batchelement3i = rsurface.modelelement3i;
11508 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11509 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11510 rsurface.batchelement3s = rsurface.modelelement3s;
11511 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11512 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11514 // if any dynamic vertex processing has to occur in software, we copy the
11515 // entire surface list together before processing to rebase the vertices
11516 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11518 // if any gaps exist and we do not have a static vertex buffer, we have to
11519 // copy the surface list together to avoid wasting upload bandwidth on the
11520 // vertices in the gaps.
11522 // if gaps exist and we have a static vertex buffer, we still have to
11523 // combine the index buffer ranges into one dynamic index buffer.
11525 // in all cases we end up with data that can be drawn in one call.
11527 if (!dynamicvertex)
11529 // static vertex data, just set pointers...
11530 rsurface.batchgeneratedvertex = false;
11531 // if there are gaps, we want to build a combined index buffer,
11532 // otherwise use the original static buffer with an appropriate offset
11537 for (i = 0;i < texturenumsurfaces;i++)
11539 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11540 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11541 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11542 numtriangles += surfacenumtriangles;
11544 rsurface.batchelement3i = rsurface.array_batchelement3i;
11545 rsurface.batchelement3i_indexbuffer = NULL;
11546 rsurface.batchelement3i_bufferoffset = 0;
11547 rsurface.batchelement3s = NULL;
11548 rsurface.batchelement3s_indexbuffer = NULL;
11549 rsurface.batchelement3s_bufferoffset = 0;
11550 if (endvertex <= 65536)
11552 rsurface.batchelement3s = rsurface.array_batchelement3s;
11553 for (i = 0;i < numtriangles*3;i++)
11554 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11556 rsurface.batchfirsttriangle = firsttriangle;
11557 rsurface.batchnumtriangles = numtriangles;
11562 // something needs software processing, do it for real...
11563 // we only directly handle interleaved array data in this case...
11564 rsurface.batchgeneratedvertex = true;
11566 // now copy the vertex data into a combined array and make an index array
11567 // (this is what Quake3 does all the time)
11568 //if (gaps || rsurface.batchfirstvertex)
11570 rsurface.batchvertexposition = NULL;
11571 rsurface.batchvertexpositionbuffer = NULL;
11572 rsurface.batchvertexmesh = NULL;
11573 rsurface.batchvertexmeshbuffer = NULL;
11574 rsurface.batchvertex3f = NULL;
11575 rsurface.batchvertex3f_vertexbuffer = NULL;
11576 rsurface.batchvertex3f_bufferoffset = 0;
11577 rsurface.batchsvector3f = NULL;
11578 rsurface.batchsvector3f_vertexbuffer = NULL;
11579 rsurface.batchsvector3f_bufferoffset = 0;
11580 rsurface.batchtvector3f = NULL;
11581 rsurface.batchtvector3f_vertexbuffer = NULL;
11582 rsurface.batchtvector3f_bufferoffset = 0;
11583 rsurface.batchnormal3f = NULL;
11584 rsurface.batchnormal3f_vertexbuffer = NULL;
11585 rsurface.batchnormal3f_bufferoffset = 0;
11586 rsurface.batchlightmapcolor4f = NULL;
11587 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11588 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11589 rsurface.batchtexcoordtexture2f = NULL;
11590 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11591 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11592 rsurface.batchtexcoordlightmap2f = NULL;
11593 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11594 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11595 rsurface.batchelement3i = rsurface.array_batchelement3i;
11596 rsurface.batchelement3i_indexbuffer = NULL;
11597 rsurface.batchelement3i_bufferoffset = 0;
11598 rsurface.batchelement3s = NULL;
11599 rsurface.batchelement3s_indexbuffer = NULL;
11600 rsurface.batchelement3s_bufferoffset = 0;
11601 // we'll only be setting up certain arrays as needed
11602 if (batchneed & BATCHNEED_VERTEXPOSITION)
11603 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11604 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11605 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11606 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11607 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11608 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11609 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11610 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11612 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11613 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11615 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11616 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11617 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11618 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11619 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11620 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11623 for (i = 0;i < texturenumsurfaces;i++)
11625 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11626 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11627 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11628 surfaceadjustvertex = numvertices - surfacefirstvertex;
11629 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11630 // copy only the data requested
11631 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11632 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11633 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11634 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11635 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11637 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11638 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11639 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11640 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11641 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11643 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11644 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11646 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11647 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11648 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11649 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11650 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11651 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11653 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11654 numvertices += surfacenumvertices;
11655 numtriangles += surfacenumtriangles;
11658 // generate a 16bit index array as well if possible
11659 // (in general, dynamic batches fit)
11660 if (numvertices <= 65536)
11662 rsurface.batchelement3s = rsurface.array_batchelement3s;
11663 for (i = 0;i < numtriangles*3;i++)
11664 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11667 // since we've copied everything, the batch now starts at 0
11668 rsurface.batchfirstvertex = 0;
11669 rsurface.batchnumvertices = numvertices;
11670 rsurface.batchfirsttriangle = 0;
11671 rsurface.batchnumtriangles = numtriangles;
11674 // q1bsp surfaces rendered in vertex color mode have to have colors
11675 // calculated based on lightstyles
11676 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11678 // generate color arrays for the surfaces in this list
11682 const int *offsets;
11683 const unsigned char *lm;
11685 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11686 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11687 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11688 for (i = 0;i < texturenumsurfaces;i++)
11690 surface = texturesurfacelist[i];
11691 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11692 surfacenumvertices = surface->num_vertices;
11693 if (surface->lightmapinfo->samples)
11695 for (j = 0;j < surfacenumvertices;j++)
11697 lm = surface->lightmapinfo->samples + offsets[j];
11698 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11699 VectorScale(lm, scale, c);
11700 if (surface->lightmapinfo->styles[1] != 255)
11702 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11704 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11705 VectorMA(c, scale, lm, c);
11706 if (surface->lightmapinfo->styles[2] != 255)
11709 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11710 VectorMA(c, scale, lm, c);
11711 if (surface->lightmapinfo->styles[3] != 255)
11714 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11715 VectorMA(c, scale, lm, c);
11722 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);
11728 for (j = 0;j < surfacenumvertices;j++)
11730 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11737 // if vertices are deformed (sprite flares and things in maps, possibly
11738 // water waves, bulges and other deformations), modify the copied vertices
11740 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11742 switch (deform->deform)
11745 case Q3DEFORM_PROJECTIONSHADOW:
11746 case Q3DEFORM_TEXT0:
11747 case Q3DEFORM_TEXT1:
11748 case Q3DEFORM_TEXT2:
11749 case Q3DEFORM_TEXT3:
11750 case Q3DEFORM_TEXT4:
11751 case Q3DEFORM_TEXT5:
11752 case Q3DEFORM_TEXT6:
11753 case Q3DEFORM_TEXT7:
11754 case Q3DEFORM_NONE:
11756 case Q3DEFORM_AUTOSPRITE:
11757 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11758 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11759 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11760 VectorNormalize(newforward);
11761 VectorNormalize(newright);
11762 VectorNormalize(newup);
11763 // a single autosprite surface can contain multiple sprites...
11764 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11766 VectorClear(center);
11767 for (i = 0;i < 4;i++)
11768 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11769 VectorScale(center, 0.25f, center);
11770 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11771 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11772 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11773 for (i = 0;i < 4;i++)
11775 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11776 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11779 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11780 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11781 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);
11782 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11783 rsurface.batchvertex3f_vertexbuffer = NULL;
11784 rsurface.batchvertex3f_bufferoffset = 0;
11785 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11786 rsurface.batchsvector3f_vertexbuffer = NULL;
11787 rsurface.batchsvector3f_bufferoffset = 0;
11788 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11789 rsurface.batchtvector3f_vertexbuffer = NULL;
11790 rsurface.batchtvector3f_bufferoffset = 0;
11791 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11792 rsurface.batchnormal3f_vertexbuffer = NULL;
11793 rsurface.batchnormal3f_bufferoffset = 0;
11795 case Q3DEFORM_AUTOSPRITE2:
11796 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11797 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11798 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11799 VectorNormalize(newforward);
11800 VectorNormalize(newright);
11801 VectorNormalize(newup);
11803 const float *v1, *v2;
11813 memset(shortest, 0, sizeof(shortest));
11814 // a single autosprite surface can contain multiple sprites...
11815 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11817 VectorClear(center);
11818 for (i = 0;i < 4;i++)
11819 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11820 VectorScale(center, 0.25f, center);
11821 // find the two shortest edges, then use them to define the
11822 // axis vectors for rotating around the central axis
11823 for (i = 0;i < 6;i++)
11825 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11826 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11827 l = VectorDistance2(v1, v2);
11828 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11829 if (v1[2] != v2[2])
11830 l += (1.0f / 1024.0f);
11831 if (shortest[0].length2 > l || i == 0)
11833 shortest[1] = shortest[0];
11834 shortest[0].length2 = l;
11835 shortest[0].v1 = v1;
11836 shortest[0].v2 = v2;
11838 else if (shortest[1].length2 > l || i == 1)
11840 shortest[1].length2 = l;
11841 shortest[1].v1 = v1;
11842 shortest[1].v2 = v2;
11845 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11846 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11847 // this calculates the right vector from the shortest edge
11848 // and the up vector from the edge midpoints
11849 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11850 VectorNormalize(right);
11851 VectorSubtract(end, start, up);
11852 VectorNormalize(up);
11853 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11854 VectorSubtract(rsurface.localvieworigin, center, forward);
11855 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11856 VectorNegate(forward, forward);
11857 VectorReflect(forward, 0, up, forward);
11858 VectorNormalize(forward);
11859 CrossProduct(up, forward, newright);
11860 VectorNormalize(newright);
11861 // rotate the quad around the up axis vector, this is made
11862 // especially easy by the fact we know the quad is flat,
11863 // so we only have to subtract the center position and
11864 // measure distance along the right vector, and then
11865 // multiply that by the newright vector and add back the
11867 // we also need to subtract the old position to undo the
11868 // displacement from the center, which we do with a
11869 // DotProduct, the subtraction/addition of center is also
11870 // optimized into DotProducts here
11871 l = DotProduct(right, center);
11872 for (i = 0;i < 4;i++)
11874 v1 = rsurface.batchvertex3f + 3*(j+i);
11875 f = DotProduct(right, v1) - l;
11876 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11880 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11881 rsurface.batchvertex3f_vertexbuffer = NULL;
11882 rsurface.batchvertex3f_bufferoffset = 0;
11883 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11885 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11886 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11887 rsurface.batchnormal3f_vertexbuffer = NULL;
11888 rsurface.batchnormal3f_bufferoffset = 0;
11890 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11892 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);
11893 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11894 rsurface.batchsvector3f_vertexbuffer = NULL;
11895 rsurface.batchsvector3f_bufferoffset = 0;
11896 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11897 rsurface.batchtvector3f_vertexbuffer = NULL;
11898 rsurface.batchtvector3f_bufferoffset = 0;
11901 case Q3DEFORM_NORMAL:
11902 // deform the normals to make reflections wavey
11903 for (j = 0;j < rsurface.batchnumvertices;j++)
11906 float *normal = rsurface.array_batchnormal3f + 3*j;
11907 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11908 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11909 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]);
11910 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]);
11911 VectorNormalize(normal);
11913 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11914 rsurface.batchnormal3f_vertexbuffer = NULL;
11915 rsurface.batchnormal3f_bufferoffset = 0;
11916 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11918 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);
11919 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11920 rsurface.batchsvector3f_vertexbuffer = NULL;
11921 rsurface.batchsvector3f_bufferoffset = 0;
11922 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11923 rsurface.batchtvector3f_vertexbuffer = NULL;
11924 rsurface.batchtvector3f_bufferoffset = 0;
11927 case Q3DEFORM_WAVE:
11928 // deform vertex array to make wavey water and flags and such
11929 waveparms[0] = deform->waveparms[0];
11930 waveparms[1] = deform->waveparms[1];
11931 waveparms[2] = deform->waveparms[2];
11932 waveparms[3] = deform->waveparms[3];
11933 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11934 break; // if wavefunc is a nop, don't make a dynamic vertex array
11935 // this is how a divisor of vertex influence on deformation
11936 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11937 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11938 for (j = 0;j < rsurface.batchnumvertices;j++)
11940 // if the wavefunc depends on time, evaluate it per-vertex
11943 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11944 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11946 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11948 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11949 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11950 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11951 rsurface.batchvertex3f_vertexbuffer = NULL;
11952 rsurface.batchvertex3f_bufferoffset = 0;
11953 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11954 rsurface.batchnormal3f_vertexbuffer = NULL;
11955 rsurface.batchnormal3f_bufferoffset = 0;
11956 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11958 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);
11959 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11960 rsurface.batchsvector3f_vertexbuffer = NULL;
11961 rsurface.batchsvector3f_bufferoffset = 0;
11962 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11963 rsurface.batchtvector3f_vertexbuffer = NULL;
11964 rsurface.batchtvector3f_bufferoffset = 0;
11967 case Q3DEFORM_BULGE:
11968 // deform vertex array to make the surface have moving bulges
11969 for (j = 0;j < rsurface.batchnumvertices;j++)
11971 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11972 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11974 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11975 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11976 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11977 rsurface.batchvertex3f_vertexbuffer = NULL;
11978 rsurface.batchvertex3f_bufferoffset = 0;
11979 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11980 rsurface.batchnormal3f_vertexbuffer = NULL;
11981 rsurface.batchnormal3f_bufferoffset = 0;
11982 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11984 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);
11985 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11986 rsurface.batchsvector3f_vertexbuffer = NULL;
11987 rsurface.batchsvector3f_bufferoffset = 0;
11988 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11989 rsurface.batchtvector3f_vertexbuffer = NULL;
11990 rsurface.batchtvector3f_bufferoffset = 0;
11993 case Q3DEFORM_MOVE:
11994 // deform vertex array
11995 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11996 break; // if wavefunc is a nop, don't make a dynamic vertex array
11997 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11998 VectorScale(deform->parms, scale, waveparms);
11999 for (j = 0;j < rsurface.batchnumvertices;j++)
12000 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12001 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12002 rsurface.batchvertex3f_vertexbuffer = NULL;
12003 rsurface.batchvertex3f_bufferoffset = 0;
12008 // generate texcoords based on the chosen texcoord source
12009 switch(rsurface.texture->tcgen.tcgen)
12012 case Q3TCGEN_TEXTURE:
12014 case Q3TCGEN_LIGHTMAP:
12015 if (rsurface.batchtexcoordlightmap2f)
12016 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12017 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12018 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12019 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12021 case Q3TCGEN_VECTOR:
12022 for (j = 0;j < rsurface.batchnumvertices;j++)
12024 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12025 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12027 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12028 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12029 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12031 case Q3TCGEN_ENVIRONMENT:
12032 // make environment reflections using a spheremap
12033 for (j = 0;j < rsurface.batchnumvertices;j++)
12035 // identical to Q3A's method, but executed in worldspace so
12036 // carried models can be shiny too
12038 float viewer[3], d, reflected[3], worldreflected[3];
12040 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12041 // VectorNormalize(viewer);
12043 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12045 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12046 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12047 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12048 // note: this is proportinal to viewer, so we can normalize later
12050 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12051 VectorNormalize(worldreflected);
12053 // note: this sphere map only uses world x and z!
12054 // so positive and negative y will LOOK THE SAME.
12055 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12056 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12058 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12059 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12060 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12063 // the only tcmod that needs software vertex processing is turbulent, so
12064 // check for it here and apply the changes if needed
12065 // and we only support that as the first one
12066 // (handling a mixture of turbulent and other tcmods would be problematic
12067 // without punting it entirely to a software path)
12068 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12070 amplitude = rsurface.texture->tcmods[0].parms[1];
12071 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12072 for (j = 0;j < rsurface.batchnumvertices;j++)
12074 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);
12075 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12077 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12078 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12079 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12082 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12084 // convert the modified arrays to vertex structs
12085 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12086 rsurface.batchvertexmeshbuffer = NULL;
12087 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12088 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12089 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12090 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12091 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12092 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12093 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12095 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12097 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12098 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12101 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12102 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12103 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12104 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12105 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12106 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12107 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12108 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12109 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12112 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12114 // convert the modified arrays to vertex structs
12115 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12116 rsurface.batchvertexpositionbuffer = NULL;
12117 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12118 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12120 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12121 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12125 void RSurf_DrawBatch(void)
12127 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);
12130 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12132 // pick the closest matching water plane
12133 int planeindex, vertexindex, bestplaneindex = -1;
12137 r_waterstate_waterplane_t *p;
12139 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12141 if(p->camera_entity != rsurface.texture->camera_entity)
12144 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12145 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12147 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12148 d += fabs(PlaneDiff(vert, &p->plane));
12150 if (bestd > d || bestplaneindex < 0)
12153 bestplaneindex = planeindex;
12156 return bestplaneindex;
12159 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12162 for (i = 0;i < rsurface.batchnumvertices;i++)
12163 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12164 rsurface.passcolor4f = rsurface.array_passcolor4f;
12165 rsurface.passcolor4f_vertexbuffer = 0;
12166 rsurface.passcolor4f_bufferoffset = 0;
12169 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12176 if (rsurface.passcolor4f)
12178 // generate color arrays
12179 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)
12181 f = RSurf_FogVertex(v);
12190 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12192 f = RSurf_FogVertex(v);
12199 rsurface.passcolor4f = rsurface.array_passcolor4f;
12200 rsurface.passcolor4f_vertexbuffer = 0;
12201 rsurface.passcolor4f_bufferoffset = 0;
12204 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12211 if (!rsurface.passcolor4f)
12213 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)
12215 f = RSurf_FogVertex(v);
12216 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12217 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12218 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12221 rsurface.passcolor4f = rsurface.array_passcolor4f;
12222 rsurface.passcolor4f_vertexbuffer = 0;
12223 rsurface.passcolor4f_bufferoffset = 0;
12226 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12231 if (!rsurface.passcolor4f)
12233 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12240 rsurface.passcolor4f = rsurface.array_passcolor4f;
12241 rsurface.passcolor4f_vertexbuffer = 0;
12242 rsurface.passcolor4f_bufferoffset = 0;
12245 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12250 if (!rsurface.passcolor4f)
12252 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12254 c2[0] = c[0] + r_refdef.scene.ambient;
12255 c2[1] = c[1] + r_refdef.scene.ambient;
12256 c2[2] = c[2] + r_refdef.scene.ambient;
12259 rsurface.passcolor4f = rsurface.array_passcolor4f;
12260 rsurface.passcolor4f_vertexbuffer = 0;
12261 rsurface.passcolor4f_bufferoffset = 0;
12264 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12267 rsurface.passcolor4f = NULL;
12268 rsurface.passcolor4f_vertexbuffer = 0;
12269 rsurface.passcolor4f_bufferoffset = 0;
12270 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12271 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12272 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12273 GL_Color(r, g, b, a);
12274 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12278 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12280 // TODO: optimize applyfog && applycolor case
12281 // just apply fog if necessary, and tint the fog color array if necessary
12282 rsurface.passcolor4f = NULL;
12283 rsurface.passcolor4f_vertexbuffer = 0;
12284 rsurface.passcolor4f_bufferoffset = 0;
12285 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12286 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12287 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12288 GL_Color(r, g, b, a);
12292 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12295 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12296 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12297 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12298 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12299 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12300 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12301 GL_Color(r, g, b, a);
12305 static void RSurf_DrawBatch_GL11_ClampColor(void)
12310 if (!rsurface.passcolor4f)
12312 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12314 c2[0] = bound(0.0f, c1[0], 1.0f);
12315 c2[1] = bound(0.0f, c1[1], 1.0f);
12316 c2[2] = bound(0.0f, c1[2], 1.0f);
12317 c2[3] = bound(0.0f, c1[3], 1.0f);
12321 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12329 vec3_t ambientcolor;
12330 vec3_t diffusecolor;
12334 VectorCopy(rsurface.modellight_lightdir, lightdir);
12335 f = 0.5f * r_refdef.lightmapintensity;
12336 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12337 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12338 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12339 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12340 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12341 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12343 if (VectorLength2(diffusecolor) > 0)
12345 // q3-style directional shading
12346 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)
12348 if ((f = DotProduct(n, lightdir)) > 0)
12349 VectorMA(ambientcolor, f, diffusecolor, c);
12351 VectorCopy(ambientcolor, c);
12358 rsurface.passcolor4f = rsurface.array_passcolor4f;
12359 rsurface.passcolor4f_vertexbuffer = 0;
12360 rsurface.passcolor4f_bufferoffset = 0;
12361 *applycolor = false;
12365 *r = ambientcolor[0];
12366 *g = ambientcolor[1];
12367 *b = ambientcolor[2];
12368 rsurface.passcolor4f = NULL;
12369 rsurface.passcolor4f_vertexbuffer = 0;
12370 rsurface.passcolor4f_bufferoffset = 0;
12374 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12376 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12377 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12378 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12379 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12380 GL_Color(r, g, b, a);
12384 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12390 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12392 f = 1 - RSurf_FogVertex(v);
12400 void RSurf_SetupDepthAndCulling(void)
12402 // submodels are biased to avoid z-fighting with world surfaces that they
12403 // may be exactly overlapping (avoids z-fighting artifacts on certain
12404 // doors and things in Quake maps)
12405 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12406 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12407 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12408 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12411 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12413 // transparent sky would be ridiculous
12414 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12416 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12417 skyrenderlater = true;
12418 RSurf_SetupDepthAndCulling();
12419 GL_DepthMask(true);
12420 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12421 // skymasking on them, and Quake3 never did sky masking (unlike
12422 // software Quake and software Quake2), so disable the sky masking
12423 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12424 // and skymasking also looks very bad when noclipping outside the
12425 // level, so don't use it then either.
12426 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12428 R_Mesh_ResetTextureState();
12429 if (skyrendermasked)
12431 R_SetupShader_DepthOrShadow();
12432 // depth-only (masking)
12433 GL_ColorMask(0,0,0,0);
12434 // just to make sure that braindead drivers don't draw
12435 // anything despite that colormask...
12436 GL_BlendFunc(GL_ZERO, GL_ONE);
12437 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12438 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12442 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12444 GL_BlendFunc(GL_ONE, GL_ZERO);
12445 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12446 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12447 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12450 if (skyrendermasked)
12451 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12453 R_Mesh_ResetTextureState();
12454 GL_Color(1, 1, 1, 1);
12457 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12458 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12459 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12461 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12465 // render screenspace normalmap to texture
12466 GL_DepthMask(true);
12467 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12472 // bind lightmap texture
12474 // water/refraction/reflection/camera surfaces have to be handled specially
12475 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12477 int start, end, startplaneindex;
12478 for (start = 0;start < texturenumsurfaces;start = end)
12480 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12481 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12483 // now that we have a batch using the same planeindex, render it
12484 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12486 // render water or distortion background
12487 GL_DepthMask(true);
12488 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));
12490 // blend surface on top
12491 GL_DepthMask(false);
12492 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12495 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12497 // render surface with reflection texture as input
12498 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12499 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));
12506 // render surface batch normally
12507 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12508 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12512 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12514 // OpenGL 1.3 path - anything not completely ancient
12515 qboolean applycolor;
12518 const texturelayer_t *layer;
12519 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);
12520 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12522 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12525 int layertexrgbscale;
12526 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12528 if (layerindex == 0)
12529 GL_AlphaTest(true);
12532 GL_AlphaTest(false);
12533 GL_DepthFunc(GL_EQUAL);
12536 GL_DepthMask(layer->depthmask && writedepth);
12537 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12538 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12540 layertexrgbscale = 4;
12541 VectorScale(layer->color, 0.25f, layercolor);
12543 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12545 layertexrgbscale = 2;
12546 VectorScale(layer->color, 0.5f, layercolor);
12550 layertexrgbscale = 1;
12551 VectorScale(layer->color, 1.0f, layercolor);
12553 layercolor[3] = layer->color[3];
12554 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12555 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12556 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12557 switch (layer->type)
12559 case TEXTURELAYERTYPE_LITTEXTURE:
12560 // single-pass lightmapped texture with 2x rgbscale
12561 R_Mesh_TexBind(0, r_texture_white);
12562 R_Mesh_TexMatrix(0, NULL);
12563 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12564 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12565 R_Mesh_TexBind(1, layer->texture);
12566 R_Mesh_TexMatrix(1, &layer->texmatrix);
12567 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12568 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12569 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12570 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12571 else if (rsurface.uselightmaptexture)
12572 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12574 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12576 case TEXTURELAYERTYPE_TEXTURE:
12577 // singletexture unlit texture with transparency support
12578 R_Mesh_TexBind(0, layer->texture);
12579 R_Mesh_TexMatrix(0, &layer->texmatrix);
12580 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12581 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12582 R_Mesh_TexBind(1, 0);
12583 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12584 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12586 case TEXTURELAYERTYPE_FOG:
12587 // singletexture fogging
12588 if (layer->texture)
12590 R_Mesh_TexBind(0, layer->texture);
12591 R_Mesh_TexMatrix(0, &layer->texmatrix);
12592 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12597 R_Mesh_TexBind(0, 0);
12598 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12600 R_Mesh_TexBind(1, 0);
12601 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12602 // generate a color array for the fog pass
12603 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12604 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12608 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12611 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12613 GL_DepthFunc(GL_LEQUAL);
12614 GL_AlphaTest(false);
12618 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12620 // OpenGL 1.1 - crusty old voodoo path
12623 const texturelayer_t *layer;
12624 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);
12625 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12627 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12629 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12631 if (layerindex == 0)
12632 GL_AlphaTest(true);
12635 GL_AlphaTest(false);
12636 GL_DepthFunc(GL_EQUAL);
12639 GL_DepthMask(layer->depthmask && writedepth);
12640 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12641 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12642 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12643 switch (layer->type)
12645 case TEXTURELAYERTYPE_LITTEXTURE:
12646 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12648 // two-pass lit texture with 2x rgbscale
12649 // first the lightmap pass
12650 R_Mesh_TexBind(0, r_texture_white);
12651 R_Mesh_TexMatrix(0, NULL);
12652 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12653 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12654 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12655 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12656 else if (rsurface.uselightmaptexture)
12657 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12659 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12660 // then apply the texture to it
12661 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12662 R_Mesh_TexBind(0, layer->texture);
12663 R_Mesh_TexMatrix(0, &layer->texmatrix);
12664 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12665 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12666 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);
12670 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12671 R_Mesh_TexBind(0, layer->texture);
12672 R_Mesh_TexMatrix(0, &layer->texmatrix);
12673 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12674 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12675 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12676 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);
12678 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);
12681 case TEXTURELAYERTYPE_TEXTURE:
12682 // singletexture unlit texture with transparency support
12683 R_Mesh_TexBind(0, layer->texture);
12684 R_Mesh_TexMatrix(0, &layer->texmatrix);
12685 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12686 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12687 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);
12689 case TEXTURELAYERTYPE_FOG:
12690 // singletexture fogging
12691 if (layer->texture)
12693 R_Mesh_TexBind(0, layer->texture);
12694 R_Mesh_TexMatrix(0, &layer->texmatrix);
12695 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12696 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12700 R_Mesh_TexBind(0, 0);
12701 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12703 // generate a color array for the fog pass
12704 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12705 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12709 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12712 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12714 GL_DepthFunc(GL_LEQUAL);
12715 GL_AlphaTest(false);
12719 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12723 r_vertexgeneric_t *batchvertex;
12726 GL_AlphaTest(false);
12727 R_Mesh_ResetTextureState();
12728 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12730 if(rsurface.texture && rsurface.texture->currentskinframe)
12732 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12733 c[3] *= rsurface.texture->currentalpha;
12743 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12745 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12746 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12747 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12750 // brighten it up (as texture value 127 means "unlit")
12751 c[0] *= 2 * r_refdef.view.colorscale;
12752 c[1] *= 2 * r_refdef.view.colorscale;
12753 c[2] *= 2 * r_refdef.view.colorscale;
12755 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12756 c[3] *= r_wateralpha.value;
12758 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12760 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12761 GL_DepthMask(false);
12763 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12765 GL_BlendFunc(GL_ONE, GL_ONE);
12766 GL_DepthMask(false);
12768 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12770 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12771 GL_DepthMask(false);
12773 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12775 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12776 GL_DepthMask(false);
12780 GL_BlendFunc(GL_ONE, GL_ZERO);
12781 GL_DepthMask(writedepth);
12784 if (r_showsurfaces.integer == 3)
12786 rsurface.passcolor4f = NULL;
12788 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12790 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12792 rsurface.passcolor4f = NULL;
12793 rsurface.passcolor4f_vertexbuffer = 0;
12794 rsurface.passcolor4f_bufferoffset = 0;
12796 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12798 qboolean applycolor = true;
12801 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12803 r_refdef.lightmapintensity = 1;
12804 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12805 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12809 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12811 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12812 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12813 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12816 if(!rsurface.passcolor4f)
12817 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12819 RSurf_DrawBatch_GL11_ApplyAmbient();
12820 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12821 if(r_refdef.fogenabled)
12822 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12823 RSurf_DrawBatch_GL11_ClampColor();
12825 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12826 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12829 else if (!r_refdef.view.showdebug)
12831 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12832 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12833 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12835 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12836 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12838 R_Mesh_PrepareVertices_Generic_Unlock();
12841 else if (r_showsurfaces.integer == 4)
12843 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12844 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12845 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12847 unsigned char c = vi << 3;
12848 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12849 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12851 R_Mesh_PrepareVertices_Generic_Unlock();
12854 else if (r_showsurfaces.integer == 2)
12857 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12858 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12859 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12861 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12862 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12863 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12864 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12865 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12866 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12867 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12869 R_Mesh_PrepareVertices_Generic_Unlock();
12870 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12874 int texturesurfaceindex;
12876 const msurface_t *surface;
12877 unsigned char surfacecolor4ub[4];
12878 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12879 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12883 surface = texturesurfacelist[texturesurfaceindex];
12884 k = (int)(((size_t)surface) / sizeof(msurface_t));
12885 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12886 for (j = 0;j < surface->num_vertices;j++)
12888 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12889 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12893 R_Mesh_PrepareVertices_Generic_Unlock();
12898 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12901 RSurf_SetupDepthAndCulling();
12902 if (r_showsurfaces.integer)
12904 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12907 switch (vid.renderpath)
12909 case RENDERPATH_GL20:
12910 case RENDERPATH_CGGL:
12911 case RENDERPATH_D3D9:
12912 case RENDERPATH_D3D10:
12913 case RENDERPATH_D3D11:
12914 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12916 case RENDERPATH_GL13:
12917 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12919 case RENDERPATH_GL11:
12920 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12926 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12929 RSurf_SetupDepthAndCulling();
12930 if (r_showsurfaces.integer)
12932 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12935 switch (vid.renderpath)
12937 case RENDERPATH_GL20:
12938 case RENDERPATH_CGGL:
12939 case RENDERPATH_D3D9:
12940 case RENDERPATH_D3D10:
12941 case RENDERPATH_D3D11:
12942 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12944 case RENDERPATH_GL13:
12945 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12947 case RENDERPATH_GL11:
12948 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12954 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12957 int texturenumsurfaces, endsurface;
12958 texture_t *texture;
12959 const msurface_t *surface;
12960 #define MAXBATCH_TRANSPARENTSURFACES 256
12961 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12963 // if the model is static it doesn't matter what value we give for
12964 // wantnormals and wanttangents, so this logic uses only rules applicable
12965 // to a model, knowing that they are meaningless otherwise
12966 if (ent == r_refdef.scene.worldentity)
12967 RSurf_ActiveWorldEntity();
12968 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12969 RSurf_ActiveModelEntity(ent, false, false, false);
12972 switch (vid.renderpath)
12974 case RENDERPATH_GL20:
12975 case RENDERPATH_CGGL:
12976 case RENDERPATH_D3D9:
12977 case RENDERPATH_D3D10:
12978 case RENDERPATH_D3D11:
12979 RSurf_ActiveModelEntity(ent, true, true, false);
12981 case RENDERPATH_GL13:
12982 case RENDERPATH_GL11:
12983 RSurf_ActiveModelEntity(ent, true, false, false);
12988 if (r_transparentdepthmasking.integer)
12990 qboolean setup = false;
12991 for (i = 0;i < numsurfaces;i = j)
12994 surface = rsurface.modelsurfaces + surfacelist[i];
12995 texture = surface->texture;
12996 rsurface.texture = R_GetCurrentTexture(texture);
12997 rsurface.lightmaptexture = NULL;
12998 rsurface.deluxemaptexture = NULL;
12999 rsurface.uselightmaptexture = false;
13000 // scan ahead until we find a different texture
13001 endsurface = min(i + 1024, numsurfaces);
13002 texturenumsurfaces = 0;
13003 texturesurfacelist[texturenumsurfaces++] = surface;
13004 for (;j < endsurface;j++)
13006 surface = rsurface.modelsurfaces + surfacelist[j];
13007 if (texture != surface->texture)
13009 texturesurfacelist[texturenumsurfaces++] = surface;
13011 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13013 // render the range of surfaces as depth
13017 GL_ColorMask(0,0,0,0);
13019 GL_DepthTest(true);
13020 GL_BlendFunc(GL_ONE, GL_ZERO);
13021 GL_DepthMask(true);
13022 GL_AlphaTest(false);
13023 R_Mesh_ResetTextureState();
13024 R_SetupShader_DepthOrShadow();
13026 RSurf_SetupDepthAndCulling();
13027 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13028 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13032 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13035 for (i = 0;i < numsurfaces;i = j)
13038 surface = rsurface.modelsurfaces + surfacelist[i];
13039 texture = surface->texture;
13040 rsurface.texture = R_GetCurrentTexture(texture);
13041 rsurface.lightmaptexture = surface->lightmaptexture;
13042 rsurface.deluxemaptexture = surface->deluxemaptexture;
13043 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13044 // scan ahead until we find a different texture
13045 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13046 texturenumsurfaces = 0;
13047 texturesurfacelist[texturenumsurfaces++] = surface;
13048 for (;j < endsurface;j++)
13050 surface = rsurface.modelsurfaces + surfacelist[j];
13051 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13053 texturesurfacelist[texturenumsurfaces++] = surface;
13055 // render the range of surfaces
13056 if (ent == r_refdef.scene.worldentity)
13057 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13059 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13061 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13062 GL_AlphaTest(false);
13065 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13067 // transparent surfaces get pushed off into the transparent queue
13068 int surfacelistindex;
13069 const msurface_t *surface;
13070 vec3_t tempcenter, center;
13071 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13073 surface = texturesurfacelist[surfacelistindex];
13074 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13075 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13076 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13077 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13078 if (queueentity->transparent_offset) // transparent offset
13080 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13081 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13082 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13084 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13088 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13090 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13092 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13094 RSurf_SetupDepthAndCulling();
13095 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13096 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13100 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13102 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13105 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13108 if (!rsurface.texture->currentnumlayers)
13110 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13111 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13113 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13115 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13116 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13117 else if (!rsurface.texture->currentnumlayers)
13119 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13121 // in the deferred case, transparent surfaces were queued during prepass
13122 if (!r_shadow_usingdeferredprepass)
13123 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13127 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13128 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13133 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13136 texture_t *texture;
13137 // break the surface list down into batches by texture and use of lightmapping
13138 for (i = 0;i < numsurfaces;i = j)
13141 // texture is the base texture pointer, rsurface.texture is the
13142 // current frame/skin the texture is directing us to use (for example
13143 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13144 // use skin 1 instead)
13145 texture = surfacelist[i]->texture;
13146 rsurface.texture = R_GetCurrentTexture(texture);
13147 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13148 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13149 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13150 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13152 // if this texture is not the kind we want, skip ahead to the next one
13153 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13157 // simply scan ahead until we find a different texture or lightmap state
13158 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13160 // render the range of surfaces
13161 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13165 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13169 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13172 if (!rsurface.texture->currentnumlayers)
13174 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13175 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13177 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13179 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13180 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13181 else if (!rsurface.texture->currentnumlayers)
13183 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13185 // in the deferred case, transparent surfaces were queued during prepass
13186 if (!r_shadow_usingdeferredprepass)
13187 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13191 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13192 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13197 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13200 texture_t *texture;
13201 // break the surface list down into batches by texture and use of lightmapping
13202 for (i = 0;i < numsurfaces;i = j)
13205 // texture is the base texture pointer, rsurface.texture is the
13206 // current frame/skin the texture is directing us to use (for example
13207 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13208 // use skin 1 instead)
13209 texture = surfacelist[i]->texture;
13210 rsurface.texture = R_GetCurrentTexture(texture);
13211 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13212 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13213 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13214 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13216 // if this texture is not the kind we want, skip ahead to the next one
13217 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13221 // simply scan ahead until we find a different texture or lightmap state
13222 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13224 // render the range of surfaces
13225 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13229 float locboxvertex3f[6*4*3] =
13231 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13232 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13233 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13234 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13235 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13236 1,0,0, 0,0,0, 0,1,0, 1,1,0
13239 unsigned short locboxelements[6*2*3] =
13244 12,13,14, 12,14,15,
13245 16,17,18, 16,18,19,
13249 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13252 cl_locnode_t *loc = (cl_locnode_t *)ent;
13254 float vertex3f[6*4*3];
13256 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13257 GL_DepthMask(false);
13258 GL_DepthRange(0, 1);
13259 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13260 GL_DepthTest(true);
13261 GL_CullFace(GL_NONE);
13262 R_EntityMatrix(&identitymatrix);
13264 R_Mesh_ResetTextureState();
13266 i = surfacelist[0];
13267 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13268 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13269 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13270 surfacelist[0] < 0 ? 0.5f : 0.125f);
13272 if (VectorCompare(loc->mins, loc->maxs))
13274 VectorSet(size, 2, 2, 2);
13275 VectorMA(loc->mins, -0.5f, size, mins);
13279 VectorCopy(loc->mins, mins);
13280 VectorSubtract(loc->maxs, loc->mins, size);
13283 for (i = 0;i < 6*4*3;)
13284 for (j = 0;j < 3;j++, i++)
13285 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13287 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13288 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13289 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13292 void R_DrawLocs(void)
13295 cl_locnode_t *loc, *nearestloc;
13297 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13298 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13300 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13301 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13305 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13307 if (decalsystem->decals)
13308 Mem_Free(decalsystem->decals);
13309 memset(decalsystem, 0, sizeof(*decalsystem));
13312 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)
13315 tridecal_t *decals;
13318 // expand or initialize the system
13319 if (decalsystem->maxdecals <= decalsystem->numdecals)
13321 decalsystem_t old = *decalsystem;
13322 qboolean useshortelements;
13323 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13324 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13325 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)));
13326 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13327 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13328 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13329 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13330 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13331 if (decalsystem->numdecals)
13332 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13334 Mem_Free(old.decals);
13335 for (i = 0;i < decalsystem->maxdecals*3;i++)
13336 decalsystem->element3i[i] = i;
13337 if (useshortelements)
13338 for (i = 0;i < decalsystem->maxdecals*3;i++)
13339 decalsystem->element3s[i] = i;
13342 // grab a decal and search for another free slot for the next one
13343 decals = decalsystem->decals;
13344 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13345 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13347 decalsystem->freedecal = i;
13348 if (decalsystem->numdecals <= i)
13349 decalsystem->numdecals = i + 1;
13351 // initialize the decal
13353 decal->triangleindex = triangleindex;
13354 decal->surfaceindex = surfaceindex;
13355 decal->decalsequence = decalsequence;
13356 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13357 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13358 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13359 decal->color4ub[0][3] = 255;
13360 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13361 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13362 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13363 decal->color4ub[1][3] = 255;
13364 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13365 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13366 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13367 decal->color4ub[2][3] = 255;
13368 decal->vertex3f[0][0] = v0[0];
13369 decal->vertex3f[0][1] = v0[1];
13370 decal->vertex3f[0][2] = v0[2];
13371 decal->vertex3f[1][0] = v1[0];
13372 decal->vertex3f[1][1] = v1[1];
13373 decal->vertex3f[1][2] = v1[2];
13374 decal->vertex3f[2][0] = v2[0];
13375 decal->vertex3f[2][1] = v2[1];
13376 decal->vertex3f[2][2] = v2[2];
13377 decal->texcoord2f[0][0] = t0[0];
13378 decal->texcoord2f[0][1] = t0[1];
13379 decal->texcoord2f[1][0] = t1[0];
13380 decal->texcoord2f[1][1] = t1[1];
13381 decal->texcoord2f[2][0] = t2[0];
13382 decal->texcoord2f[2][1] = t2[1];
13385 extern cvar_t cl_decals_bias;
13386 extern cvar_t cl_decals_models;
13387 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13388 // baseparms, parms, temps
13389 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)
13394 const float *vertex3f;
13396 float points[2][9][3];
13403 e = rsurface.modelelement3i + 3*triangleindex;
13405 vertex3f = rsurface.modelvertex3f;
13407 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13409 index = 3*e[cornerindex];
13410 VectorCopy(vertex3f + index, v[cornerindex]);
13413 //TriangleNormal(v[0], v[1], v[2], normal);
13414 //if (DotProduct(normal, localnormal) < 0.0f)
13416 // clip by each of the box planes formed from the projection matrix
13417 // if anything survives, we emit the decal
13418 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]);
13421 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]);
13424 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]);
13427 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]);
13430 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]);
13433 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]);
13436 // some part of the triangle survived, so we have to accept it...
13439 // dynamic always uses the original triangle
13441 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13443 index = 3*e[cornerindex];
13444 VectorCopy(vertex3f + index, v[cornerindex]);
13447 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13449 // convert vertex positions to texcoords
13450 Matrix4x4_Transform(projection, v[cornerindex], temp);
13451 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13452 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13453 // calculate distance fade from the projection origin
13454 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13455 f = bound(0.0f, f, 1.0f);
13456 c[cornerindex][0] = r * f;
13457 c[cornerindex][1] = g * f;
13458 c[cornerindex][2] = b * f;
13459 c[cornerindex][3] = 1.0f;
13460 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13463 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);
13465 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13466 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);
13468 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)
13470 matrix4x4_t projection;
13471 decalsystem_t *decalsystem;
13474 const msurface_t *surface;
13475 const msurface_t *surfaces;
13476 const int *surfacelist;
13477 const texture_t *texture;
13479 int numsurfacelist;
13480 int surfacelistindex;
13483 float localorigin[3];
13484 float localnormal[3];
13485 float localmins[3];
13486 float localmaxs[3];
13489 float planes[6][4];
13492 int bih_triangles_count;
13493 int bih_triangles[256];
13494 int bih_surfaces[256];
13496 decalsystem = &ent->decalsystem;
13497 model = ent->model;
13498 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13500 R_DecalSystem_Reset(&ent->decalsystem);
13504 if (!model->brush.data_leafs && !cl_decals_models.integer)
13506 if (decalsystem->model)
13507 R_DecalSystem_Reset(decalsystem);
13511 if (decalsystem->model != model)
13512 R_DecalSystem_Reset(decalsystem);
13513 decalsystem->model = model;
13515 RSurf_ActiveModelEntity(ent, false, false, false);
13517 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13518 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13519 VectorNormalize(localnormal);
13520 localsize = worldsize*rsurface.inversematrixscale;
13521 localmins[0] = localorigin[0] - localsize;
13522 localmins[1] = localorigin[1] - localsize;
13523 localmins[2] = localorigin[2] - localsize;
13524 localmaxs[0] = localorigin[0] + localsize;
13525 localmaxs[1] = localorigin[1] + localsize;
13526 localmaxs[2] = localorigin[2] + localsize;
13528 //VectorCopy(localnormal, planes[4]);
13529 //VectorVectors(planes[4], planes[2], planes[0]);
13530 AnglesFromVectors(angles, localnormal, NULL, false);
13531 AngleVectors(angles, planes[0], planes[2], planes[4]);
13532 VectorNegate(planes[0], planes[1]);
13533 VectorNegate(planes[2], planes[3]);
13534 VectorNegate(planes[4], planes[5]);
13535 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13536 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13537 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13538 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13539 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13540 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13545 matrix4x4_t forwardprojection;
13546 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13547 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13552 float projectionvector[4][3];
13553 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13554 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13555 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13556 projectionvector[0][0] = planes[0][0] * ilocalsize;
13557 projectionvector[0][1] = planes[1][0] * ilocalsize;
13558 projectionvector[0][2] = planes[2][0] * ilocalsize;
13559 projectionvector[1][0] = planes[0][1] * ilocalsize;
13560 projectionvector[1][1] = planes[1][1] * ilocalsize;
13561 projectionvector[1][2] = planes[2][1] * ilocalsize;
13562 projectionvector[2][0] = planes[0][2] * ilocalsize;
13563 projectionvector[2][1] = planes[1][2] * ilocalsize;
13564 projectionvector[2][2] = planes[2][2] * ilocalsize;
13565 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13566 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13567 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13568 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13572 dynamic = model->surfmesh.isanimated;
13573 numsurfacelist = model->nummodelsurfaces;
13574 surfacelist = model->sortedmodelsurfaces;
13575 surfaces = model->data_surfaces;
13578 bih_triangles_count = -1;
13581 if(model->render_bih.numleafs)
13582 bih = &model->render_bih;
13583 else if(model->collision_bih.numleafs)
13584 bih = &model->collision_bih;
13587 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13588 if(bih_triangles_count == 0)
13590 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13592 if(bih_triangles_count > 0)
13594 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13596 surfaceindex = bih_surfaces[triangleindex];
13597 surface = surfaces + surfaceindex;
13598 texture = surface->texture;
13599 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13601 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13603 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13608 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13610 surfaceindex = surfacelist[surfacelistindex];
13611 surface = surfaces + surfaceindex;
13612 // check cull box first because it rejects more than any other check
13613 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13615 // skip transparent surfaces
13616 texture = surface->texture;
13617 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13619 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13621 numtriangles = surface->num_triangles;
13622 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13623 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13628 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13629 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)
13631 int renderentityindex;
13632 float worldmins[3];
13633 float worldmaxs[3];
13634 entity_render_t *ent;
13636 if (!cl_decals_newsystem.integer)
13639 worldmins[0] = worldorigin[0] - worldsize;
13640 worldmins[1] = worldorigin[1] - worldsize;
13641 worldmins[2] = worldorigin[2] - worldsize;
13642 worldmaxs[0] = worldorigin[0] + worldsize;
13643 worldmaxs[1] = worldorigin[1] + worldsize;
13644 worldmaxs[2] = worldorigin[2] + worldsize;
13646 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13648 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13650 ent = r_refdef.scene.entities[renderentityindex];
13651 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13654 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13658 typedef struct r_decalsystem_splatqueue_s
13660 vec3_t worldorigin;
13661 vec3_t worldnormal;
13667 r_decalsystem_splatqueue_t;
13669 int r_decalsystem_numqueued = 0;
13670 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13672 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)
13674 r_decalsystem_splatqueue_t *queue;
13676 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13679 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13680 VectorCopy(worldorigin, queue->worldorigin);
13681 VectorCopy(worldnormal, queue->worldnormal);
13682 Vector4Set(queue->color, r, g, b, a);
13683 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13684 queue->worldsize = worldsize;
13685 queue->decalsequence = cl.decalsequence++;
13688 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13691 r_decalsystem_splatqueue_t *queue;
13693 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13694 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);
13695 r_decalsystem_numqueued = 0;
13698 extern cvar_t cl_decals_max;
13699 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13702 decalsystem_t *decalsystem = &ent->decalsystem;
13709 if (!decalsystem->numdecals)
13712 if (r_showsurfaces.integer)
13715 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13717 R_DecalSystem_Reset(decalsystem);
13721 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13722 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13724 if (decalsystem->lastupdatetime)
13725 frametime = (cl.time - decalsystem->lastupdatetime);
13728 decalsystem->lastupdatetime = cl.time;
13729 decal = decalsystem->decals;
13730 numdecals = decalsystem->numdecals;
13732 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13734 if (decal->color4ub[0][3])
13736 decal->lived += frametime;
13737 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13739 memset(decal, 0, sizeof(*decal));
13740 if (decalsystem->freedecal > i)
13741 decalsystem->freedecal = i;
13745 decal = decalsystem->decals;
13746 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13749 // collapse the array by shuffling the tail decals into the gaps
13752 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13753 decalsystem->freedecal++;
13754 if (decalsystem->freedecal == numdecals)
13756 decal[decalsystem->freedecal] = decal[--numdecals];
13759 decalsystem->numdecals = numdecals;
13761 if (numdecals <= 0)
13763 // if there are no decals left, reset decalsystem
13764 R_DecalSystem_Reset(decalsystem);
13768 extern skinframe_t *decalskinframe;
13769 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13772 decalsystem_t *decalsystem = &ent->decalsystem;
13781 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13784 numdecals = decalsystem->numdecals;
13788 if (r_showsurfaces.integer)
13791 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13793 R_DecalSystem_Reset(decalsystem);
13797 // if the model is static it doesn't matter what value we give for
13798 // wantnormals and wanttangents, so this logic uses only rules applicable
13799 // to a model, knowing that they are meaningless otherwise
13800 if (ent == r_refdef.scene.worldentity)
13801 RSurf_ActiveWorldEntity();
13803 RSurf_ActiveModelEntity(ent, false, false, false);
13805 decalsystem->lastupdatetime = cl.time;
13806 decal = decalsystem->decals;
13808 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13810 // update vertex positions for animated models
13811 v3f = decalsystem->vertex3f;
13812 c4f = decalsystem->color4f;
13813 t2f = decalsystem->texcoord2f;
13814 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13816 if (!decal->color4ub[0][3])
13819 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13822 // update color values for fading decals
13823 if (decal->lived >= cl_decals_time.value)
13825 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13826 alpha *= (1.0f/255.0f);
13829 alpha = 1.0f/255.0f;
13831 c4f[ 0] = decal->color4ub[0][0] * alpha;
13832 c4f[ 1] = decal->color4ub[0][1] * alpha;
13833 c4f[ 2] = decal->color4ub[0][2] * alpha;
13835 c4f[ 4] = decal->color4ub[1][0] * alpha;
13836 c4f[ 5] = decal->color4ub[1][1] * alpha;
13837 c4f[ 6] = decal->color4ub[1][2] * alpha;
13839 c4f[ 8] = decal->color4ub[2][0] * alpha;
13840 c4f[ 9] = decal->color4ub[2][1] * alpha;
13841 c4f[10] = decal->color4ub[2][2] * alpha;
13844 t2f[0] = decal->texcoord2f[0][0];
13845 t2f[1] = decal->texcoord2f[0][1];
13846 t2f[2] = decal->texcoord2f[1][0];
13847 t2f[3] = decal->texcoord2f[1][1];
13848 t2f[4] = decal->texcoord2f[2][0];
13849 t2f[5] = decal->texcoord2f[2][1];
13851 // update vertex positions for animated models
13852 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13854 e = rsurface.modelelement3i + 3*decal->triangleindex;
13855 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13856 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13857 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13861 VectorCopy(decal->vertex3f[0], v3f);
13862 VectorCopy(decal->vertex3f[1], v3f + 3);
13863 VectorCopy(decal->vertex3f[2], v3f + 6);
13866 if (r_refdef.fogenabled)
13868 alpha = RSurf_FogVertex(v3f);
13869 VectorScale(c4f, alpha, c4f);
13870 alpha = RSurf_FogVertex(v3f + 3);
13871 VectorScale(c4f + 4, alpha, c4f + 4);
13872 alpha = RSurf_FogVertex(v3f + 6);
13873 VectorScale(c4f + 8, alpha, c4f + 8);
13884 r_refdef.stats.drawndecals += numtris;
13886 // now render the decals all at once
13887 // (this assumes they all use one particle font texture!)
13888 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);
13889 R_Mesh_ResetTextureState();
13890 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13891 GL_DepthMask(false);
13892 GL_DepthRange(0, 1);
13893 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13894 GL_DepthTest(true);
13895 GL_CullFace(GL_NONE);
13896 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13897 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13898 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13902 static void R_DrawModelDecals(void)
13906 // fade faster when there are too many decals
13907 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13908 for (i = 0;i < r_refdef.scene.numentities;i++)
13909 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13911 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13912 for (i = 0;i < r_refdef.scene.numentities;i++)
13913 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13914 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13916 R_DecalSystem_ApplySplatEntitiesQueue();
13918 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13919 for (i = 0;i < r_refdef.scene.numentities;i++)
13920 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13922 r_refdef.stats.totaldecals += numdecals;
13924 if (r_showsurfaces.integer)
13927 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13929 for (i = 0;i < r_refdef.scene.numentities;i++)
13931 if (!r_refdef.viewcache.entityvisible[i])
13933 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13934 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13938 extern cvar_t mod_collision_bih;
13939 void R_DrawDebugModel(void)
13941 entity_render_t *ent = rsurface.entity;
13942 int i, j, k, l, flagsmask;
13943 const msurface_t *surface;
13944 dp_model_t *model = ent->model;
13947 switch(vid.renderpath)
13949 case RENDERPATH_GL11:
13950 case RENDERPATH_GL13:
13951 case RENDERPATH_GL20:
13952 case RENDERPATH_CGGL:
13954 case RENDERPATH_D3D9:
13955 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13957 case RENDERPATH_D3D10:
13958 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13960 case RENDERPATH_D3D11:
13961 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13965 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13967 R_Mesh_ResetTextureState();
13968 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13969 GL_DepthRange(0, 1);
13970 GL_DepthTest(!r_showdisabledepthtest.integer);
13971 GL_DepthMask(false);
13972 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13974 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13978 qboolean cullbox = ent == r_refdef.scene.worldentity;
13979 const q3mbrush_t *brush;
13980 const bih_t *bih = &model->collision_bih;
13981 const bih_leaf_t *bihleaf;
13982 float vertex3f[3][3];
13983 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13985 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13987 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13989 switch (bihleaf->type)
13992 brush = model->brush.data_brushes + bihleaf->itemindex;
13993 if (brush->colbrushf && brush->colbrushf->numtriangles)
13995 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);
13996 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13997 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14000 case BIH_COLLISIONTRIANGLE:
14001 triangleindex = bihleaf->itemindex;
14002 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14003 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14004 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14005 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);
14006 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14007 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14009 case BIH_RENDERTRIANGLE:
14010 triangleindex = bihleaf->itemindex;
14011 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14012 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14013 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14014 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);
14015 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14016 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14022 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14024 if (r_showtris.integer || r_shownormals.integer)
14026 if (r_showdisabledepthtest.integer)
14028 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14029 GL_DepthMask(false);
14033 GL_BlendFunc(GL_ONE, GL_ZERO);
14034 GL_DepthMask(true);
14036 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14038 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14040 rsurface.texture = R_GetCurrentTexture(surface->texture);
14041 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14043 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14044 if (r_showtris.value > 0)
14046 if (!rsurface.texture->currentlayers->depthmask)
14047 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14048 else if (ent == r_refdef.scene.worldentity)
14049 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14051 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14052 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14053 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14055 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14058 if (r_shownormals.value < 0)
14060 qglBegin(GL_LINES);
14061 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14063 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14064 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14065 qglVertex3f(v[0], v[1], v[2]);
14066 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14067 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14068 qglVertex3f(v[0], v[1], v[2]);
14073 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14075 qglBegin(GL_LINES);
14076 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14078 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14079 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14080 qglVertex3f(v[0], v[1], v[2]);
14081 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14082 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14083 qglVertex3f(v[0], v[1], v[2]);
14087 qglBegin(GL_LINES);
14088 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14090 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14091 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14092 qglVertex3f(v[0], v[1], v[2]);
14093 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14094 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14095 qglVertex3f(v[0], v[1], v[2]);
14099 qglBegin(GL_LINES);
14100 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14102 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14103 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14104 qglVertex3f(v[0], v[1], v[2]);
14105 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14106 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14107 qglVertex3f(v[0], v[1], v[2]);
14114 rsurface.texture = NULL;
14118 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14119 int r_maxsurfacelist = 0;
14120 const msurface_t **r_surfacelist = NULL;
14121 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14123 int i, j, endj, flagsmask;
14124 dp_model_t *model = r_refdef.scene.worldmodel;
14125 msurface_t *surfaces;
14126 unsigned char *update;
14127 int numsurfacelist = 0;
14131 if (r_maxsurfacelist < model->num_surfaces)
14133 r_maxsurfacelist = model->num_surfaces;
14135 Mem_Free((msurface_t**)r_surfacelist);
14136 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14139 RSurf_ActiveWorldEntity();
14141 surfaces = model->data_surfaces;
14142 update = model->brushq1.lightmapupdateflags;
14144 // update light styles on this submodel
14145 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14147 model_brush_lightstyleinfo_t *style;
14148 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14150 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14152 int *list = style->surfacelist;
14153 style->value = r_refdef.scene.lightstylevalue[style->style];
14154 for (j = 0;j < style->numsurfaces;j++)
14155 update[list[j]] = true;
14160 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14164 R_DrawDebugModel();
14165 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14169 rsurface.lightmaptexture = NULL;
14170 rsurface.deluxemaptexture = NULL;
14171 rsurface.uselightmaptexture = false;
14172 rsurface.texture = NULL;
14173 rsurface.rtlight = NULL;
14174 numsurfacelist = 0;
14175 // add visible surfaces to draw list
14176 for (i = 0;i < model->nummodelsurfaces;i++)
14178 j = model->sortedmodelsurfaces[i];
14179 if (r_refdef.viewcache.world_surfacevisible[j])
14180 r_surfacelist[numsurfacelist++] = surfaces + j;
14182 // update lightmaps if needed
14183 if (model->brushq1.firstrender)
14185 model->brushq1.firstrender = false;
14186 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14188 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14192 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14193 if (r_refdef.viewcache.world_surfacevisible[j])
14195 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14197 // don't do anything if there were no surfaces
14198 if (!numsurfacelist)
14200 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14203 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14204 GL_AlphaTest(false);
14206 // add to stats if desired
14207 if (r_speeds.integer && !skysurfaces && !depthonly)
14209 r_refdef.stats.world_surfaces += numsurfacelist;
14210 for (j = 0;j < numsurfacelist;j++)
14211 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14214 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14217 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14219 int i, j, endj, flagsmask;
14220 dp_model_t *model = ent->model;
14221 msurface_t *surfaces;
14222 unsigned char *update;
14223 int numsurfacelist = 0;
14227 if (r_maxsurfacelist < model->num_surfaces)
14229 r_maxsurfacelist = model->num_surfaces;
14231 Mem_Free((msurface_t **)r_surfacelist);
14232 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14235 // if the model is static it doesn't matter what value we give for
14236 // wantnormals and wanttangents, so this logic uses only rules applicable
14237 // to a model, knowing that they are meaningless otherwise
14238 if (ent == r_refdef.scene.worldentity)
14239 RSurf_ActiveWorldEntity();
14240 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14241 RSurf_ActiveModelEntity(ent, false, false, false);
14243 RSurf_ActiveModelEntity(ent, true, true, true);
14244 else if (depthonly)
14246 switch (vid.renderpath)
14248 case RENDERPATH_GL20:
14249 case RENDERPATH_CGGL:
14250 case RENDERPATH_D3D9:
14251 case RENDERPATH_D3D10:
14252 case RENDERPATH_D3D11:
14253 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14255 case RENDERPATH_GL13:
14256 case RENDERPATH_GL11:
14257 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14263 switch (vid.renderpath)
14265 case RENDERPATH_GL20:
14266 case RENDERPATH_CGGL:
14267 case RENDERPATH_D3D9:
14268 case RENDERPATH_D3D10:
14269 case RENDERPATH_D3D11:
14270 RSurf_ActiveModelEntity(ent, true, true, false);
14272 case RENDERPATH_GL13:
14273 case RENDERPATH_GL11:
14274 RSurf_ActiveModelEntity(ent, true, false, false);
14279 surfaces = model->data_surfaces;
14280 update = model->brushq1.lightmapupdateflags;
14282 // update light styles
14283 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14285 model_brush_lightstyleinfo_t *style;
14286 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14288 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14290 int *list = style->surfacelist;
14291 style->value = r_refdef.scene.lightstylevalue[style->style];
14292 for (j = 0;j < style->numsurfaces;j++)
14293 update[list[j]] = true;
14298 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14302 R_DrawDebugModel();
14303 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14307 rsurface.lightmaptexture = NULL;
14308 rsurface.deluxemaptexture = NULL;
14309 rsurface.uselightmaptexture = false;
14310 rsurface.texture = NULL;
14311 rsurface.rtlight = NULL;
14312 numsurfacelist = 0;
14313 // add visible surfaces to draw list
14314 for (i = 0;i < model->nummodelsurfaces;i++)
14315 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14316 // don't do anything if there were no surfaces
14317 if (!numsurfacelist)
14319 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14322 // update lightmaps if needed
14326 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14331 R_BuildLightMap(ent, surfaces + j);
14336 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14338 R_BuildLightMap(ent, surfaces + j);
14339 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14340 GL_AlphaTest(false);
14342 // add to stats if desired
14343 if (r_speeds.integer && !skysurfaces && !depthonly)
14345 r_refdef.stats.entities_surfaces += numsurfacelist;
14346 for (j = 0;j < numsurfacelist;j++)
14347 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14350 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14353 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14355 static texture_t texture;
14356 static msurface_t surface;
14357 const msurface_t *surfacelist = &surface;
14359 // fake enough texture and surface state to render this geometry
14361 texture.update_lastrenderframe = -1; // regenerate this texture
14362 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14363 texture.currentskinframe = skinframe;
14364 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14365 texture.offsetmapping = OFFSETMAPPING_OFF;
14366 texture.offsetscale = 1;
14367 texture.specularscalemod = 1;
14368 texture.specularpowermod = 1;
14370 surface.texture = &texture;
14371 surface.num_triangles = numtriangles;
14372 surface.num_firsttriangle = firsttriangle;
14373 surface.num_vertices = numvertices;
14374 surface.num_firstvertex = firstvertex;
14377 rsurface.texture = R_GetCurrentTexture(surface.texture);
14378 rsurface.lightmaptexture = NULL;
14379 rsurface.deluxemaptexture = NULL;
14380 rsurface.uselightmaptexture = false;
14381 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14384 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)
14386 static msurface_t surface;
14387 const msurface_t *surfacelist = &surface;
14389 // fake enough texture and surface state to render this geometry
14391 surface.texture = texture;
14392 surface.num_triangles = numtriangles;
14393 surface.num_firsttriangle = firsttriangle;
14394 surface.num_vertices = numvertices;
14395 surface.num_firstvertex = firstvertex;
14398 rsurface.texture = R_GetCurrentTexture(surface.texture);
14399 rsurface.lightmaptexture = NULL;
14400 rsurface.deluxemaptexture = NULL;
14401 rsurface.uselightmaptexture = false;
14402 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);