2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
137 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
143 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
144 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
145 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
147 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
171 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
173 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
187 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
189 extern cvar_t v_glslgamma;
191 extern qboolean v_flipped_state;
193 static struct r_bloomstate_s
198 int bloomwidth, bloomheight;
200 int screentexturewidth, screentextureheight;
201 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
203 int bloomtexturewidth, bloomtextureheight;
204 rtexture_t *texture_bloom;
206 // arrays for rendering the screen passes
207 float screentexcoord2f[8];
208 float bloomtexcoord2f[8];
209 float offsettexcoord2f[8];
211 r_viewport_t viewport;
215 r_waterstate_t r_waterstate;
217 /// shadow volume bsp struct with automatically growing nodes buffer
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
249 typedef struct r_qwskincache_s
251 char name[MAX_QPATH];
252 skinframe_t *skinframe;
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
269 const float r_d3dscreenvertex3f[12] =
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
280 for (i = 0;i < verts;i++)
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
294 for (i = 0;i < verts;i++)
304 // FIXME: move this to client?
307 if (gamemode == GAME_NEHAHRA)
309 Cvar_Set("gl_fogenable", "0");
310 Cvar_Set("gl_fogdensity", "0.2");
311 Cvar_Set("gl_fogred", "0.3");
312 Cvar_Set("gl_foggreen", "0.3");
313 Cvar_Set("gl_fogblue", "0.3");
315 r_refdef.fog_density = 0;
316 r_refdef.fog_red = 0;
317 r_refdef.fog_green = 0;
318 r_refdef.fog_blue = 0;
319 r_refdef.fog_alpha = 1;
320 r_refdef.fog_start = 0;
321 r_refdef.fog_end = 16384;
322 r_refdef.fog_height = 1<<30;
323 r_refdef.fog_fadedepth = 128;
324 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
327 static void R_BuildBlankTextures(void)
329 unsigned char data[4];
330 data[2] = 128; // normal X
331 data[1] = 128; // normal Y
332 data[0] = 255; // normal Z
333 data[3] = 128; // height
334 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
339 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
344 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
349 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352 static void R_BuildNoTexture(void)
355 unsigned char pix[16][16][4];
356 // this makes a light grey/dark grey checkerboard texture
357 for (y = 0;y < 16;y++)
359 for (x = 0;x < 16;x++)
361 if ((y < 8) ^ (x < 8))
377 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
380 static void R_BuildWhiteCube(void)
382 unsigned char data[6*1*1*4];
383 memset(data, 255, sizeof(data));
384 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildNormalizationCube(void)
391 vec_t s, t, intensity;
394 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395 for (side = 0;side < 6;side++)
397 for (y = 0;y < NORMSIZE;y++)
399 for (x = 0;x < NORMSIZE;x++)
401 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437 intensity = 127.0f / sqrt(DotProduct(v, v));
438 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441 data[((side*64+y)*64+x)*4+3] = 255;
445 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
449 static void R_BuildFogTexture(void)
453 unsigned char data1[FOGWIDTH][4];
454 //unsigned char data2[FOGWIDTH][4];
457 r_refdef.fogmasktable_start = r_refdef.fog_start;
458 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459 r_refdef.fogmasktable_range = r_refdef.fogrange;
460 r_refdef.fogmasktable_density = r_refdef.fog_density;
462 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
465 d = (x * r - r_refdef.fogmasktable_start);
466 if(developer_extra.integer)
467 Con_DPrintf("%f ", d);
469 if (r_fog_exp2.integer)
470 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
472 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473 if(developer_extra.integer)
474 Con_DPrintf(" : %f ", alpha);
475 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476 if(developer_extra.integer)
477 Con_DPrintf(" = %f\n", alpha);
478 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
481 for (x = 0;x < FOGWIDTH;x++)
483 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
488 //data2[x][0] = 255 - b;
489 //data2[x][1] = 255 - b;
490 //data2[x][2] = 255 - b;
493 if (r_texture_fogattenuation)
495 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
500 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
505 static void R_BuildFogHeightTexture(void)
507 unsigned char *inpixels;
515 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516 if (r_refdef.fogheighttexturename[0])
517 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
520 r_refdef.fog_height_tablesize = 0;
521 if (r_texture_fogheighttexture)
522 R_FreeTexture(r_texture_fogheighttexture);
523 r_texture_fogheighttexture = NULL;
524 if (r_refdef.fog_height_table2d)
525 Mem_Free(r_refdef.fog_height_table2d);
526 r_refdef.fog_height_table2d = NULL;
527 if (r_refdef.fog_height_table1d)
528 Mem_Free(r_refdef.fog_height_table1d);
529 r_refdef.fog_height_table1d = NULL;
533 r_refdef.fog_height_tablesize = size;
534 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
538 // LordHavoc: now the magic - what is that table2d for? it is a cooked
539 // average fog color table accounting for every fog layer between a point
540 // and the camera. (Note: attenuation is handled separately!)
541 for (y = 0;y < size;y++)
543 for (x = 0;x < size;x++)
549 for (j = x;j <= y;j++)
551 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
557 for (j = x;j >= y;j--)
559 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
564 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
570 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
573 //=======================================================================================================================================================
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
590 "#ifdef USESHADOWMAP2D\n"
591 "# ifdef GL_EXT_gpu_shader4\n"
592 "# extension GL_EXT_gpu_shader4 : enable\n"
594 "# ifdef GL_ARB_texture_gather\n"
595 "# extension GL_ARB_texture_gather : enable\n"
597 "# ifdef GL_AMD_texture_texture4\n"
598 "# extension GL_AMD_texture_texture4 : enable\n"
603 "//#ifdef USESHADOWSAMPLER\n"
604 "//# extension GL_ARB_shadow : enable\n"
607 "//#ifdef __GLSL_CG_DATA_TYPES\n"
608 "//# define myhalf half\n"
609 "//# define myhalf2 half2\n"
610 "//# define myhalf3 half3\n"
611 "//# define myhalf4 half4\n"
613 "# define myhalf float\n"
614 "# define myhalf2 vec2\n"
615 "# define myhalf3 vec3\n"
616 "# define myhalf4 vec4\n"
619 "#ifdef VERTEX_SHADER\n"
620 "uniform mat4 ModelViewProjectionMatrix;\n"
623 "#ifdef MODE_DEPTH_OR_SHADOW\n"
624 "#ifdef VERTEX_SHADER\n"
627 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
630 "#else // !MODE_DEPTH_ORSHADOW\n"
635 "#ifdef MODE_SHOWDEPTH\n"
636 "#ifdef VERTEX_SHADER\n"
639 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
640 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
644 "#ifdef FRAGMENT_SHADER\n"
647 " gl_FragColor = gl_Color;\n"
650 "#else // !MODE_SHOWDEPTH\n"
655 "#ifdef MODE_POSTPROCESS\n"
656 "varying vec2 TexCoord1;\n"
657 "varying vec2 TexCoord2;\n"
659 "#ifdef VERTEX_SHADER\n"
662 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
663 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
665 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "uniform sampler2D Texture_First;\n"
673 "uniform sampler2D Texture_Second;\n"
674 "uniform vec4 BloomColorSubtract;\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
694 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
696 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
698 "#ifdef USEVIEWTINT\n"
699 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
705 " float sobel = 1.0;\n"
706 " // vec2 ts = textureSize(Texture_First, 0);\n"
707 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 " vec2 px = PixelSize;\n"
709 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
711 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
714 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
717 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
720 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
738 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
739 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
743 "#ifdef USESATURATION\n"
744 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
750 "#ifdef USEGAMMARAMPS\n"
751 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
757 "#else // !MODE_POSTPROCESS\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
769 "#ifdef VERTEX_SHADER\n"
772 " gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
776 "#ifdef USESPECULAR\n"
777 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
779 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
793 " gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
798 "#ifdef USESPECULAR\n"
799 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 " gl_FragColor *= tex2;\n"
804 " gl_FragColor += tex2;\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
812 "#else // !MODE_GENERIC\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
822 " gl_FrontColor = gl_Color;\n"
823 " TexCoord = gl_MultiTexCoord0.xy;\n"
824 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
835 " vec2 tc = TexCoord;\n"
836 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 " tc += BloomBlur_Parameters.xy;\n"
838 " for (i = 1;i < SAMPLES;i++)\n"
840 " color += texture2D(Texture_First, tc).rgb;\n"
841 " tc += BloomBlur_Parameters.xy;\n"
843 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
855 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 " ModelViewProjectionPosition = gl_Position;\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
876 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 " // FIXME temporary hack to detect the case that the reflection\n"
881 " // gets blackened at edges due to leaving the area that contains actual\n"
883 " // Remove this 'ack once we have a better way to stop this thing from\n"
885 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
893 "#else // !MODE_REFRACTION\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
908 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 " ModelViewProjectionPosition = gl_Position;\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
933 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
934 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
935 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
936 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
937 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
938 " // FIXME temporary hack to detect the case that the reflection\n"
939 " // gets blackened at edges due to leaving the area that contains actual\n"
941 " // Remove this 'ack once we have a better way to stop this thing from\n"
943 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
948 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
949 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
950 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
951 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
952 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
953 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
954 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
957 "#else // !MODE_WATER\n"
962 "// common definitions between vertex shader and fragment shader:\n"
964 "varying vec2 TexCoord;\n"
965 "#ifdef USEVERTEXTEXTUREBLEND\n"
966 "varying vec2 TexCoord2;\n"
968 "#ifdef USELIGHTMAP\n"
969 "varying vec2 TexCoordLightmap;\n"
972 "#ifdef MODE_LIGHTSOURCE\n"
973 "varying vec3 CubeVector;\n"
976 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
977 "varying vec3 LightVector;\n"
980 "#ifdef USEEYEVECTOR\n"
981 "varying vec3 EyeVector;\n"
984 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
987 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
988 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
989 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
990 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
993 "#ifdef USEREFLECTION\n"
994 "varying vec4 ModelViewProjectionPosition;\n"
996 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
998 "varying vec4 ModelViewPosition;\n"
1001 "#ifdef MODE_LIGHTSOURCE\n"
1002 "uniform vec3 LightPosition;\n"
1004 "uniform vec3 EyePosition;\n"
1005 "#ifdef MODE_LIGHTDIRECTION\n"
1006 "uniform vec3 LightDir;\n"
1008 "uniform vec4 FogPlane;\n"
1010 "#ifdef USESHADOWMAPORTHO\n"
1011 "varying vec3 ShadowMapTC;\n"
1018 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1020 "// fragment shader specific:\n"
1021 "#ifdef FRAGMENT_SHADER\n"
1023 "uniform sampler2D Texture_Normal;\n"
1024 "uniform sampler2D Texture_Color;\n"
1025 "uniform sampler2D Texture_Gloss;\n"
1027 "uniform sampler2D Texture_Glow;\n"
1029 "#ifdef USEVERTEXTEXTUREBLEND\n"
1030 "uniform sampler2D Texture_SecondaryNormal;\n"
1031 "uniform sampler2D Texture_SecondaryColor;\n"
1032 "uniform sampler2D Texture_SecondaryGloss;\n"
1034 "uniform sampler2D Texture_SecondaryGlow;\n"
1037 "#ifdef USECOLORMAPPING\n"
1038 "uniform sampler2D Texture_Pants;\n"
1039 "uniform sampler2D Texture_Shirt;\n"
1042 "#ifdef USEFOGHEIGHTTEXTURE\n"
1043 "uniform sampler2D Texture_FogHeightTexture;\n"
1045 "uniform sampler2D Texture_FogMask;\n"
1047 "#ifdef USELIGHTMAP\n"
1048 "uniform sampler2D Texture_Lightmap;\n"
1050 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1051 "uniform sampler2D Texture_Deluxemap;\n"
1053 "#ifdef USEREFLECTION\n"
1054 "uniform sampler2D Texture_Reflection;\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform sampler2D Texture_ScreenDepth;\n"
1059 "uniform sampler2D Texture_ScreenNormalMap;\n"
1061 "#ifdef USEDEFERREDLIGHTMAP\n"
1062 "uniform sampler2D Texture_ScreenDiffuse;\n"
1063 "uniform sampler2D Texture_ScreenSpecular;\n"
1066 "uniform myhalf3 Color_Pants;\n"
1067 "uniform myhalf3 Color_Shirt;\n"
1068 "uniform myhalf3 FogColor;\n"
1071 "uniform float FogRangeRecip;\n"
1072 "uniform float FogPlaneViewDist;\n"
1073 "uniform float FogHeightFade;\n"
1074 "vec3 FogVertex(vec3 surfacecolor)\n"
1076 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1077 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1081 " fogfrac = fogheightpixel.a;\n"
1082 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1084 "# ifdef USEFOGOUTSIDE\n"
1085 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1087 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1089 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1094 "#ifdef USEOFFSETMAPPING\n"
1095 "uniform float OffsetMapping_Scale;\n"
1096 "vec2 OffsetMapping(vec2 TexCoord)\n"
1098 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1099 " // 14 sample relief mapping: linear search and then binary search\n"
1100 " // this basically steps forward a small amount repeatedly until it finds\n"
1101 " // itself inside solid, then jitters forward and back using decreasing\n"
1102 " // amounts to find the impact\n"
1103 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1104 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1105 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1106 " vec3 RT = vec3(TexCoord, 1);\n"
1107 " OffsetVector *= 0.1;\n"
1108 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1113 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1114 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1115 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1116 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1118 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1119 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1120 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1121 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1124 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1125 " // this basically moves forward the full distance, and then backs up based\n"
1126 " // on height of samples\n"
1127 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1128 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1129 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1130 " TexCoord += OffsetVector;\n"
1131 " OffsetVector *= 0.333;\n"
1132 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1133 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1134 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1135 " return TexCoord;\n"
1138 "#endif // USEOFFSETMAPPING\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1141 "uniform sampler2D Texture_Attenuation;\n"
1142 "uniform samplerCube Texture_Cube;\n"
1145 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1147 "#ifdef USESHADOWMAP2D\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1151 "uniform sampler2D Texture_ShadowMap2D;\n"
1155 "#ifdef USESHADOWMAPVSDCT\n"
1156 "uniform samplerCube Texture_CubeProjection;\n"
1159 "#if defined(USESHADOWMAP2D)\n"
1160 "uniform vec2 ShadowMap_TextureScale;\n"
1161 "uniform vec4 ShadowMap_Parameters;\n"
1164 "#if defined(USESHADOWMAP2D)\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1168 "# ifdef USESHADOWMAPVSDCT\n"
1169 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1171 " vec3 adir = abs(dir);\n"
1172 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1173 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1177 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1179 " vec3 adir = abs(dir);\n"
1180 " float ma = adir.z;\n"
1181 " vec4 proj = vec4(dir, 2.5);\n"
1182 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1183 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1184 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1185 " return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1189 "#endif // defined(USESHADOWMAP2D)\n"
1191 "# ifdef USESHADOWMAP2D\n"
1192 "float ShadowMapCompare(vec3 dir)\n"
1194 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1197 "# ifdef USESHADOWSAMPLER\n"
1198 "# ifdef USESHADOWMAPPCF\n"
1199 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1200 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1201 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1203 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1206 "# ifdef USESHADOWMAPPCF\n"
1207 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1208 "# ifdef GL_ARB_texture_gather\n"
1209 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1211 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1213 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1214 "# if USESHADOWMAPPCF > 1\n"
1215 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1216 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1217 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1218 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1219 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1220 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1221 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1222 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1223 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1224 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1225 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1226 " locols.yz += group2.ab;\n"
1227 " hicols.yz += group8.rg;\n"
1228 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1229 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1230 " mix(locols, hicols, offset.y);\n"
1231 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1232 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1233 " f = dot(cols, vec4(1.0/25.0));\n"
1235 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1236 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1237 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1238 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1239 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1240 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1241 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1244 "# ifdef GL_EXT_gpu_shader4\n"
1245 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1247 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1249 "# if USESHADOWMAPPCF > 1\n"
1250 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1251 " center *= ShadowMap_TextureScale;\n"
1252 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1253 " vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
1254 " vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
1255 " vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
1256 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1257 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1259 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1260 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1261 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1262 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1263 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1264 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1268 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1271 "# ifdef USESHADOWMAPORTHO\n"
1272 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1278 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1279 "#endif // FRAGMENT_SHADER\n"
1284 "#ifdef MODE_DEFERREDGEOMETRY\n"
1285 "#ifdef VERTEX_SHADER\n"
1286 "uniform mat4 TexMatrix;\n"
1287 "#ifdef USEVERTEXTEXTUREBLEND\n"
1288 "uniform mat4 BackgroundTexMatrix;\n"
1290 "uniform mat4 ModelViewMatrix;\n"
1293 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1294 "#ifdef USEVERTEXTEXTUREBLEND\n"
1295 " gl_FrontColor = gl_Color;\n"
1296 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1299 " // transform unnormalized eye direction into tangent space\n"
1300 "#ifdef USEOFFSETMAPPING\n"
1301 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1302 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1303 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1304 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1307 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1308 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1309 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1310 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1312 "#endif // VERTEX_SHADER\n"
1314 "#ifdef FRAGMENT_SHADER\n"
1317 "#ifdef USEOFFSETMAPPING\n"
1318 " // apply offsetmapping\n"
1319 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1320 "#define TexCoord TexCoordOffset\n"
1323 "#ifdef USEALPHAKILL\n"
1324 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1330 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1331 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1332 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1337 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1339 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1340 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1343 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1345 "#endif // FRAGMENT_SHADER\n"
1346 "#else // !MODE_DEFERREDGEOMETRY\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "#ifdef VERTEX_SHADER\n"
1353 "uniform mat4 ModelViewMatrix;\n"
1356 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1357 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1359 "#endif // VERTEX_SHADER\n"
1361 "#ifdef FRAGMENT_SHADER\n"
1362 "uniform mat4 ViewToLight;\n"
1363 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1364 "uniform vec2 ScreenToDepth;\n"
1365 "uniform myhalf3 DeferredColor_Ambient;\n"
1366 "uniform myhalf3 DeferredColor_Diffuse;\n"
1367 "#ifdef USESPECULAR\n"
1368 "uniform myhalf3 DeferredColor_Specular;\n"
1369 "uniform myhalf SpecularPower;\n"
1371 "uniform myhalf2 PixelToScreenTexCoord;\n"
1374 " // calculate viewspace pixel position\n"
1375 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1377 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1378 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1379 " // decode viewspace pixel normal\n"
1380 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1381 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1382 " // surfacenormal = pixel normal in viewspace\n"
1383 " // LightVector = pixel to light in viewspace\n"
1384 " // CubeVector = position in lightspace\n"
1385 " // eyevector = pixel to view in viewspace\n"
1386 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1387 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1388 "#ifdef USEDIFFUSE\n"
1389 " // calculate diffuse shading\n"
1390 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1391 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1393 "#ifdef USESPECULAR\n"
1394 " // calculate directional shading\n"
1395 " vec3 eyevector = position * -1.0;\n"
1396 "# ifdef USEEXACTSPECULARMATH\n"
1397 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1399 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1400 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1404 "#if defined(USESHADOWMAP2D)\n"
1405 " fade *= ShadowMapCompare(CubeVector);\n"
1408 "#ifdef USEDIFFUSE\n"
1409 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1411 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1413 "#ifdef USESPECULAR\n"
1414 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1416 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1419 "# ifdef USECUBEFILTER\n"
1420 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1421 " gl_FragData[0].rgb *= cubecolor;\n"
1422 " gl_FragData[1].rgb *= cubecolor;\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1431 "#ifdef VERTEX_SHADER\n"
1432 "uniform mat4 TexMatrix;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 "uniform mat4 BackgroundTexMatrix;\n"
1436 "#ifdef MODE_LIGHTSOURCE\n"
1437 "uniform mat4 ModelToLight;\n"
1439 "#ifdef USESHADOWMAPORTHO\n"
1440 "uniform mat4 ShadowMapMatrix;\n"
1444 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1445 " gl_FrontColor = gl_Color;\n"
1447 " // copy the surface texcoord\n"
1448 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1449 "#ifdef USEVERTEXTEXTUREBLEND\n"
1450 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1452 "#ifdef USELIGHTMAP\n"
1453 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 " // transform vertex position into light attenuation/cubemap space\n"
1458 " // (-1 to +1 across the light box)\n"
1459 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1461 "# ifdef USEDIFFUSE\n"
1462 " // transform unnormalized light direction into tangent space\n"
1463 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1464 " // normalize it per pixel)\n"
1465 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1466 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1467 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1468 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1472 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1473 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1474 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1475 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1478 " // transform unnormalized eye direction into tangent space\n"
1479 "#ifdef USEEYEVECTOR\n"
1480 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1481 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1482 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1483 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1487 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1488 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1491 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1492 " VectorS = gl_MultiTexCoord1.xyz;\n"
1493 " VectorT = gl_MultiTexCoord2.xyz;\n"
1494 " VectorR = gl_MultiTexCoord3.xyz;\n"
1497 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1498 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1500 "#ifdef USESHADOWMAPORTHO\n"
1501 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1504 "#ifdef USEREFLECTION\n"
1505 " ModelViewProjectionPosition = gl_Position;\n"
1508 "#endif // VERTEX_SHADER\n"
1513 "#ifdef FRAGMENT_SHADER\n"
1514 "#ifdef USEDEFERREDLIGHTMAP\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "uniform myhalf3 DeferredMod_Diffuse;\n"
1517 "uniform myhalf3 DeferredMod_Specular;\n"
1519 "uniform myhalf3 Color_Ambient;\n"
1520 "uniform myhalf3 Color_Diffuse;\n"
1521 "uniform myhalf3 Color_Specular;\n"
1522 "uniform myhalf SpecularPower;\n"
1524 "uniform myhalf3 Color_Glow;\n"
1526 "uniform myhalf Alpha;\n"
1527 "#ifdef USEREFLECTION\n"
1528 "uniform vec4 DistortScaleRefractReflect;\n"
1529 "uniform vec4 ScreenScaleRefractReflect;\n"
1530 "uniform vec4 ScreenCenterRefractReflect;\n"
1531 "uniform myhalf4 ReflectColor;\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "uniform mat4 ModelToReflectCube;\n"
1535 "uniform sampler2D Texture_ReflectMask;\n"
1536 "uniform samplerCube Texture_ReflectCube;\n"
1538 "#ifdef MODE_LIGHTDIRECTION\n"
1539 "uniform myhalf3 LightColor;\n"
1541 "#ifdef MODE_LIGHTSOURCE\n"
1542 "uniform myhalf3 LightColor;\n"
1546 "#ifdef USEOFFSETMAPPING\n"
1547 " // apply offsetmapping\n"
1548 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1549 "#define TexCoord TexCoordOffset\n"
1552 " // combine the diffuse textures (base, pants, shirt)\n"
1553 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1554 "#ifdef USEALPHAKILL\n"
1555 " if (color.a < 0.5)\n"
1558 " color.a *= Alpha;\n"
1559 "#ifdef USECOLORMAPPING\n"
1560 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1562 "#ifdef USEVERTEXTEXTUREBLEND\n"
1563 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1564 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1565 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1566 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1568 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1571 " // get the surface normal\n"
1572 "#ifdef USEVERTEXTEXTUREBLEND\n"
1573 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1575 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1578 " // get the material colors\n"
1579 " myhalf3 diffusetex = color.rgb;\n"
1580 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1581 "# ifdef USEVERTEXTEXTUREBLEND\n"
1582 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1584 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1588 "#ifdef USEREFLECTCUBE\n"
1589 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1590 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1591 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1592 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1598 "#ifdef MODE_LIGHTSOURCE\n"
1599 " // light source\n"
1600 "#ifdef USEDIFFUSE\n"
1601 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1603 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1604 "#ifdef USESPECULAR\n"
1605 "#ifdef USEEXACTSPECULARMATH\n"
1606 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1608 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1609 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1611 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1614 " color.rgb = diffusetex * Color_Ambient;\n"
1616 " color.rgb *= LightColor;\n"
1617 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1618 "#if defined(USESHADOWMAP2D)\n"
1619 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1621 "# ifdef USECUBEFILTER\n"
1622 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1624 "#endif // MODE_LIGHTSOURCE\n"
1629 "#ifdef MODE_LIGHTDIRECTION\n"
1631 "#ifdef USEDIFFUSE\n"
1632 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1634 "#define lightcolor LightColor\n"
1635 "#endif // MODE_LIGHTDIRECTION\n"
1636 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1638 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1639 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1640 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1641 " // convert modelspace light vector to tangentspace\n"
1642 " myhalf3 lightnormal;\n"
1643 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1644 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1645 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1646 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1647 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1648 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1649 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1650 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1651 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1652 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1653 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1654 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1655 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1656 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1659 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1660 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1661 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1667 "#ifdef MODE_LIGHTMAP\n"
1668 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1669 "#endif // MODE_LIGHTMAP\n"
1670 "#ifdef MODE_VERTEXCOLOR\n"
1671 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1672 "#endif // MODE_VERTEXCOLOR\n"
1673 "#ifdef MODE_FLATCOLOR\n"
1674 " color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif // MODE_FLATCOLOR\n"
1681 "# ifdef USEDIFFUSE\n"
1682 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "# ifdef USESPECULAR\n"
1684 "# ifdef USEEXACTSPECULARMATH\n"
1685 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1687 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1688 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1690 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1692 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1695 " color.rgb = diffusetex * Color_Ambient;\n"
1699 "#ifdef USESHADOWMAPORTHO\n"
1700 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1703 "#ifdef USEDEFERREDLIGHTMAP\n"
1704 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1705 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1706 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1710 "#ifdef USEVERTEXTEXTUREBLEND\n"
1711 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1713 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1718 " color.rgb = FogVertex(color.rgb);\n"
1721 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1722 "#ifdef USEREFLECTION\n"
1723 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1724 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1725 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1726 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1727 " // FIXME temporary hack to detect the case that the reflection\n"
1728 " // gets blackened at edges due to leaving the area that contains actual\n"
1730 " // Remove this 'ack once we have a better way to stop this thing from\n"
1732 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1733 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1734 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1735 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1736 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1737 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1740 " gl_FragColor = vec4(color);\n"
1742 "#endif // FRAGMENT_SHADER\n"
1744 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1745 "#endif // !MODE_DEFERREDGEOMETRY\n"
1746 "#endif // !MODE_WATER\n"
1747 "#endif // !MODE_REFRACTION\n"
1748 "#endif // !MODE_BLOOMBLUR\n"
1749 "#endif // !MODE_GENERIC\n"
1750 "#endif // !MODE_POSTPROCESS\n"
1751 "#endif // !MODE_SHOWDEPTH\n"
1752 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1756 =========================================================================================================================================================
1760 =========================================================================================================================================================
1764 =========================================================================================================================================================
1768 =========================================================================================================================================================
1772 =========================================================================================================================================================
1776 =========================================================================================================================================================
1780 =========================================================================================================================================================
1783 const char *builtincgshaderstring =
1784 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1785 "// written by Forest 'LordHavoc' Hale\n"
1786 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1788 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1789 "#if defined(USEREFLECTION)\n"
1790 "#undef USESHADOWMAPORTHO\n"
1793 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1796 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1797 "#define USELIGHTMAP\n"
1799 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1800 "#define USEEYEVECTOR\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1805 "//#undef USESHADOWMAPPCF\n"
1806 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1807 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1809 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1813 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1814 "#ifdef VERTEX_SHADER\n"
1817 "float4 gl_Vertex : POSITION,\n"
1818 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1819 "out float4 gl_Position : POSITION,\n"
1820 "out float Depth : TEXCOORD0\n"
1823 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1824 " Depth = gl_Position.z;\n"
1828 "#ifdef FRAGMENT_SHADER\n"
1831 "float Depth : TEXCOORD0,\n"
1832 "out float4 gl_FragColor : COLOR\n"
1835 "// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1836 " float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1837 " temp.yz -= floor(temp.yz);\n"
1838 " gl_FragColor = float4(temp,0);\n"
1839 "// gl_FragColor = float4(Depth,0,0,0);\n"
1842 "#else // !MODE_DEPTH_ORSHADOW\n"
1847 "#ifdef MODE_SHOWDEPTH\n"
1848 "#ifdef VERTEX_SHADER\n"
1851 "float4 gl_Vertex : POSITION,\n"
1852 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1853 "out float4 gl_Position : POSITION,\n"
1854 "out float4 gl_FrontColor : COLOR0\n"
1857 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1858 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1862 "#ifdef FRAGMENT_SHADER\n"
1865 "float4 gl_FrontColor : COLOR0,\n"
1866 "out float4 gl_FragColor : COLOR\n"
1869 " gl_FragColor = gl_FrontColor;\n"
1872 "#else // !MODE_SHOWDEPTH\n"
1877 "#ifdef MODE_POSTPROCESS\n"
1879 "#ifdef VERTEX_SHADER\n"
1882 "float4 gl_Vertex : POSITION,\n"
1883 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1884 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1885 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1886 "out float4 gl_Position : POSITION,\n"
1887 "out float2 TexCoord1 : TEXCOORD0,\n"
1888 "out float2 TexCoord2 : TEXCOORD1\n"
1891 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1892 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1894 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1899 "#ifdef FRAGMENT_SHADER\n"
1902 "float2 TexCoord1 : TEXCOORD0,\n"
1903 "float2 TexCoord2 : TEXCOORD1,\n"
1904 "uniform sampler Texture_First : register(s0),\n"
1906 "uniform sampler Texture_Second : register(s1),\n"
1908 "#ifdef USEGAMMARAMPS\n"
1909 "uniform sampler Texture_GammaRamps : register(s2),\n"
1911 "#ifdef USESATURATION\n"
1912 "uniform float Saturation : register(c30),\n"
1914 "#ifdef USEVIEWTINT\n"
1915 "uniform float4 ViewTintColor : register(c41),\n"
1917 "uniform float4 UserVec1 : register(c37),\n"
1918 "uniform float4 UserVec2 : register(c38),\n"
1919 "uniform float4 UserVec3 : register(c39),\n"
1920 "uniform float4 UserVec4 : register(c40),\n"
1921 "uniform float ClientTime : register(c2),\n"
1922 "uniform float2 PixelSize : register(c25),\n"
1923 "uniform float4 BloomColorSubtract : register(c43),\n"
1924 "out float4 gl_FragColor : COLOR\n"
1927 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1929 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1931 "#ifdef USEVIEWTINT\n"
1932 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1935 "#ifdef USEPOSTPROCESSING\n"
1936 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1937 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1938 " float sobel = 1.0;\n"
1939 " // float2 ts = textureSize(Texture_First, 0);\n"
1940 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1941 " float2 px = PixelSize;\n"
1942 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1943 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1944 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1945 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1946 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1947 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1948 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1949 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1950 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1951 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1952 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1953 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1954 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1955 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1956 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1957 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1958 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1959 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1960 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1961 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1962 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1963 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1964 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1965 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1966 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1967 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1968 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1969 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1970 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
1971 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
1972 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
1973 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
1976 "#ifdef USESATURATION\n"
1977 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1978 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1979 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1980 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
1983 "#ifdef USEGAMMARAMPS\n"
1984 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1985 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1986 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1990 "#else // !MODE_POSTPROCESS\n"
1995 "#ifdef MODE_GENERIC\n"
1996 "#ifdef VERTEX_SHADER\n"
1999 "float4 gl_Vertex : POSITION,\n"
2000 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2001 "float4 gl_Color : COLOR0,\n"
2002 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2003 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2004 "out float4 gl_Position : POSITION,\n"
2005 "out float4 gl_FrontColor : COLOR,\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "out float2 TexCoord2 : TEXCOORD1\n"
2011 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2013 " gl_FrontColor = gl_Color; // Cg is forward\n"
2015 "#ifdef USEDIFFUSE\n"
2016 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2018 "#ifdef USESPECULAR\n"
2019 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2021 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2025 "#ifdef FRAGMENT_SHADER\n"
2029 "float4 gl_FrontColor : COLOR0,\n"
2030 "float2 TexCoord1 : TEXCOORD0,\n"
2031 "float2 TexCoord2 : TEXCOORD1,\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2035 "#ifdef USESPECULAR\n"
2036 "uniform sampler Texture_Second : register(s1),\n"
2038 "out float4 gl_FragColor : COLOR\n"
2041 " gl_FragColor = gl_FrontColor;\n"
2042 "#ifdef USEDIFFUSE\n"
2043 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2046 "#ifdef USESPECULAR\n"
2047 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2048 "# ifdef USECOLORMAPPING\n"
2049 " gl_FragColor *= tex2;\n"
2052 " gl_FragColor += tex2;\n"
2054 "# ifdef USEVERTEXTEXTUREBLEND\n"
2055 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2060 "#else // !MODE_GENERIC\n"
2065 "#ifdef MODE_BLOOMBLUR\n"
2066 "#ifdef VERTEX_SHADER\n"
2069 "float4 gl_Vertex : POSITION,\n"
2070 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2071 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2072 "out float4 gl_Position : POSITION,\n"
2073 "out float2 TexCoord : TEXCOORD0\n"
2076 " TexCoord = gl_MultiTexCoord0.xy;\n"
2077 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2085 "float2 TexCoord : TEXCOORD0,\n"
2086 "uniform sampler Texture_First : register(s0),\n"
2087 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2088 "out float4 gl_FragColor : COLOR\n"
2092 " float2 tc = TexCoord;\n"
2093 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2094 " tc += BloomBlur_Parameters.xy;\n"
2095 " for (i = 1;i < SAMPLES;i++)\n"
2097 " color += tex2D(Texture_First, tc).rgb;\n"
2098 " tc += BloomBlur_Parameters.xy;\n"
2100 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2103 "#else // !MODE_BLOOMBLUR\n"
2104 "#ifdef MODE_REFRACTION\n"
2105 "#ifdef VERTEX_SHADER\n"
2108 "float4 gl_Vertex : POSITION,\n"
2109 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2110 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2111 "uniform float4x4 TexMatrix : register(c0),\n"
2112 "uniform float3 EyePosition : register(c24),\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0,\n"
2115 "out float3 EyeVector : TEXCOORD1,\n"
2116 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2119 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2120 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 " ModelViewProjectionPosition = gl_Position;\n"
2125 "#ifdef FRAGMENT_SHADER\n"
2128 "float2 TexCoord : TEXCOORD0,\n"
2129 "float3 EyeVector : TEXCOORD1,\n"
2130 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2131 "uniform sampler Texture_Normal : register(s0),\n"
2132 "uniform sampler Texture_Refraction : register(s3),\n"
2133 "uniform sampler Texture_Reflection : register(s7),\n"
2134 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2135 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2136 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2137 "uniform float4 RefractColor : register(c29),\n"
2138 "out float4 gl_FragColor : COLOR\n"
2141 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2142 " //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2143 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2144 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2145 " // FIXME temporary hack to detect the case that the reflection\n"
2146 " // gets blackened at edges due to leaving the area that contains actual\n"
2148 " // Remove this 'ack once we have a better way to stop this thing from\n"
2150 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2151 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2152 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2153 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2154 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2155 " gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2158 "#else // !MODE_REFRACTION\n"
2163 "#ifdef MODE_WATER\n"
2164 "#ifdef VERTEX_SHADER\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2172 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2173 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2174 "uniform float4x4 TexMatrix : register(c0),\n"
2175 "uniform float3 EyePosition : register(c24),\n"
2176 "out float4 gl_Position : POSITION,\n"
2177 "out float2 TexCoord : TEXCOORD0,\n"
2178 "out float3 EyeVector : TEXCOORD1,\n"
2179 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2182 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2183 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2184 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2185 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2186 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2187 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2188 " ModelViewProjectionPosition = gl_Position;\n"
2192 "#ifdef FRAGMENT_SHADER\n"
2195 "float2 TexCoord : TEXCOORD0,\n"
2196 "float3 EyeVector : TEXCOORD1,\n"
2197 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2198 "uniform sampler Texture_Normal : register(s0),\n"
2199 "uniform sampler Texture_Refraction : register(s3),\n"
2200 "uniform sampler Texture_Reflection : register(s7),\n"
2201 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2202 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2203 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2204 "uniform float4 RefractColor : register(c29),\n"
2205 "uniform float4 ReflectColor : register(c26),\n"
2206 "uniform float ReflectFactor : register(c27),\n"
2207 "uniform float ReflectOffset : register(c28),\n"
2208 "out float4 gl_FragColor : COLOR\n"
2211 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2212 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2213 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2214 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2215 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2216 " // FIXME temporary hack to detect the case that the reflection\n"
2217 " // gets blackened at edges due to leaving the area that contains actual\n"
2219 " // Remove this 'ack once we have a better way to stop this thing from\n"
2221 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2222 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2223 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2224 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2225 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2226 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2227 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2228 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2229 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2230 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2231 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2232 " gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2235 "#else // !MODE_WATER\n"
2240 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2242 "// fragment shader specific:\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2246 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2249 "#ifdef USEFOGHEIGHTTEXTURE\n"
2250 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2251 " fogfrac = fogheightpixel.a;\n"
2252 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2254 "# ifdef USEFOGOUTSIDE\n"
2255 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2257 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2259 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2264 "#ifdef USEOFFSETMAPPING\n"
2265 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2267 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2268 " // 14 sample relief mapping: linear search and then binary search\n"
2269 " // this basically steps forward a small amount repeatedly until it finds\n"
2270 " // itself inside solid, then jitters forward and back using decreasing\n"
2271 " // amounts to find the impact\n"
2272 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2273 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2274 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2275 " float3 RT = float3(TexCoord, 1);\n"
2276 " OffsetVector *= 0.1;\n"
2277 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2278 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2279 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2280 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2281 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2282 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2283 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2284 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2285 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2286 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2287 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2288 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2289 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2290 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2293 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2294 " // this basically moves forward the full distance, and then backs up based\n"
2295 " // on height of samples\n"
2296 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2297 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2298 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2299 " TexCoord += OffsetVector;\n"
2300 " OffsetVector *= 0.333;\n"
2301 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2302 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2303 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2304 " return TexCoord;\n"
2307 "#endif // USEOFFSETMAPPING\n"
2309 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2310 "#if defined(USESHADOWMAP2D)\n"
2311 "# ifdef USESHADOWMAPORTHO\n"
2312 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2314 "# ifdef USESHADOWMAPVSDCT\n"
2315 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2317 " float3 adir = abs(dir);\n"
2318 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2319 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2320 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2323 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2325 " float3 adir = abs(dir);\n"
2326 " float ma = adir.z;\n"
2327 " float4 proj = float4(dir, 2.5);\n"
2328 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2329 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2331 " return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2333 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2334 " return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2339 "#endif // defined(USESHADOWMAP2D)\n"
2341 "# ifdef USESHADOWMAP2D\n"
2342 "#ifdef USESHADOWMAPVSDCT\n"
2343 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2345 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2348 "#ifdef USESHADOWMAPVSDCT\n"
2349 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2351 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2355 "# ifdef USESHADOWSAMPLER\n"
2356 "# ifdef USESHADOWMAPPCF\n"
2357 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2358 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2359 " f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2361 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2364 "# ifdef USESHADOWMAPPCF\n"
2365 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2366 "# ifdef GL_ARB_texture_gather\n"
2367 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2369 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2371 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2372 "# if USESHADOWMAPPCF > 1\n"
2373 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2374 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2375 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2376 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2377 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2378 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2379 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2380 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2381 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2382 " float4 locols = float4(group1.ab, group3.ab);\n"
2383 " float4 hicols = float4(group7.rg, group9.rg);\n"
2384 " locols.yz += group2.ab;\n"
2385 " hicols.yz += group8.rg;\n"
2386 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2387 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2388 " lerp(locols, hicols, offset.y);\n"
2389 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2390 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2391 " f = dot(cols, float4(1.0/25.0));\n"
2393 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2394 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2395 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2396 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2397 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2398 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2399 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2402 "# ifdef GL_EXT_gpu_shader4\n"
2403 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2405 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2407 "# if USESHADOWMAPPCF > 1\n"
2408 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2409 " center *= ShadowMap_TextureScale;\n"
2410 " float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2411 " float4 row2 = step(shadowmaptc.z, float4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0)));\n"
2412 " float4 row3 = step(shadowmaptc.z, float4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0)));\n"
2413 " float4 row4 = step(shadowmaptc.z, float4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0)));\n"
2414 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2415 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2417 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2418 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2419 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2420 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2421 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2422 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2426 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2429 "# ifdef USESHADOWMAPORTHO\n"
2430 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2436 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2437 "#endif // FRAGMENT_SHADER\n"
2442 "#ifdef MODE_DEFERREDGEOMETRY\n"
2443 "#ifdef VERTEX_SHADER\n"
2446 "float4 gl_Vertex : POSITION,\n"
2447 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "float4 gl_Color : COLOR0,\n"
2451 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2452 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2453 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2454 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2455 "uniform float4x4 TexMatrix : register(c0),\n"
2456 "#ifdef USEVERTEXTEXTUREBLEND\n"
2457 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2459 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2460 "#ifdef USEOFFSETMAPPING\n"
2461 "uniform float3 EyePosition : register(c24),\n"
2463 "out float4 gl_Position : POSITION,\n"
2464 "out float4 gl_FrontColor : COLOR,\n"
2465 "out float4 TexCoordBoth : TEXCOORD0,\n"
2466 "#ifdef USEOFFSETMAPPING\n"
2467 "out float3 EyeVector : TEXCOORD2,\n"
2469 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2470 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2471 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2474 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2475 "#ifdef USEVERTEXTEXTUREBLEND\n"
2477 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2479 " gl_FrontColor = gl_Color; // Cg is forward\n"
2481 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2484 " // transform unnormalized eye direction into tangent space\n"
2485 "#ifdef USEOFFSETMAPPING\n"
2486 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2487 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2488 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2489 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2492 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2493 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2494 " VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2495 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2497 "#endif // VERTEX_SHADER\n"
2499 "#ifdef FRAGMENT_SHADER\n"
2502 "float4 TexCoordBoth : TEXCOORD0,\n"
2503 "float3 EyeVector : TEXCOORD2,\n"
2504 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2505 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2506 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2507 "uniform sampler Texture_Normal : register(s0),\n"
2508 "#ifdef USEALPHAKILL\n"
2509 "uniform sampler Texture_Color : register(s1),\n"
2511 "uniform sampler Texture_Gloss : register(s2),\n"
2512 "#ifdef USEVERTEXTEXTUREBLEND\n"
2513 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2514 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2516 "#ifdef USEOFFSETMAPPING\n"
2517 "uniform float OffsetMapping_Scale : register(c24),\n"
2519 "uniform half SpecularPower : register(c36),\n"
2520 "out float4 gl_FragColor : COLOR\n"
2523 " float2 TexCoord = TexCoordBoth.xy;\n"
2524 "#ifdef USEOFFSETMAPPING\n"
2525 " // apply offsetmapping\n"
2526 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2527 "#define TexCoord TexCoordOffset\n"
2530 "#ifdef USEALPHAKILL\n"
2531 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2535 "#ifdef USEVERTEXTEXTUREBLEND\n"
2536 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2537 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2538 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2539 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2542 "#ifdef USEVERTEXTEXTUREBLEND\n"
2543 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2544 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2546 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2547 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2550 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2552 "#endif // FRAGMENT_SHADER\n"
2553 "#else // !MODE_DEFERREDGEOMETRY\n"
2558 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2559 "#ifdef VERTEX_SHADER\n"
2562 "float4 gl_Vertex : POSITION,\n"
2563 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2564 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2565 "out float4 gl_Position : POSITION,\n"
2566 "out float4 ModelViewPosition : TEXCOORD0\n"
2569 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2570 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2572 "#endif // VERTEX_SHADER\n"
2574 "#ifdef FRAGMENT_SHADER\n"
2578 "float2 Pixel : VPOS,\n"
2580 "float2 Pixel : WPOS,\n"
2582 "float4 ModelViewPosition : TEXCOORD0,\n"
2583 "uniform float4x4 ViewToLight : register(c44),\n"
2584 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2585 "uniform float3 LightPosition : register(c23),\n"
2586 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2587 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2588 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2589 "#ifdef USESPECULAR\n"
2590 "uniform half3 DeferredColor_Specular : register(c11),\n"
2591 "uniform half SpecularPower : register(c36),\n"
2593 "uniform sampler Texture_Attenuation : register(s9),\n"
2594 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2595 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2597 "#ifdef USECUBEFILTER\n"
2598 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2601 "#ifdef USESHADOWMAP2D\n"
2602 "# ifdef USESHADOWSAMPLER\n"
2603 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2605 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2609 "#ifdef USESHADOWMAPVSDCT\n"
2610 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2613 "#if defined(USESHADOWMAP2D)\n"
2614 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2615 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2618 "out float4 gl_FragData0 : COLOR0,\n"
2619 "out float4 gl_FragData1 : COLOR1\n"
2622 " // calculate viewspace pixel position\n"
2623 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2624 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2625 " float3 position;\n"
2626 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2627 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2628 " // decode viewspace pixel normal\n"
2629 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2630 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2631 " // surfacenormal = pixel normal in viewspace\n"
2632 " // LightVector = pixel to light in viewspace\n"
2633 " // CubeVector = position in lightspace\n"
2634 " // eyevector = pixel to view in viewspace\n"
2635 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2636 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2637 "#ifdef USEDIFFUSE\n"
2638 " // calculate diffuse shading\n"
2639 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2640 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2642 "#ifdef USESPECULAR\n"
2643 " // calculate directional shading\n"
2644 " float3 eyevector = position * -1.0;\n"
2645 "# ifdef USEEXACTSPECULARMATH\n"
2646 " half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2648 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2649 " half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2653 "#if defined(USESHADOWMAP2D)\n"
2654 " fade *= ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2655 "#ifdef USESHADOWMAPVSDCT\n"
2656 ", Texture_CubeProjection\n"
2661 "#ifdef USEDIFFUSE\n"
2662 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2664 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2666 "#ifdef USESPECULAR\n"
2667 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2669 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2672 "# ifdef USECUBEFILTER\n"
2673 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2674 " gl_FragData0.rgb *= cubecolor;\n"
2675 " gl_FragData1.rgb *= cubecolor;\n"
2678 "#endif // FRAGMENT_SHADER\n"
2679 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2684 "#ifdef VERTEX_SHADER\n"
2687 "float4 gl_Vertex : POSITION,\n"
2688 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2689 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2690 "float4 gl_Color : COLOR0,\n"
2692 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2693 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2694 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2695 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2696 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2698 "uniform float3 EyePosition : register(c24),\n"
2699 "uniform float4x4 TexMatrix : register(c0),\n"
2700 "#ifdef USEVERTEXTEXTUREBLEND\n"
2701 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2703 "#ifdef MODE_LIGHTSOURCE\n"
2704 "uniform float4x4 ModelToLight : register(c20),\n"
2706 "#ifdef MODE_LIGHTSOURCE\n"
2707 "uniform float3 LightPosition : register(c27),\n"
2709 "#ifdef MODE_LIGHTDIRECTION\n"
2710 "uniform float3 LightDir : register(c26),\n"
2712 "uniform float4 FogPlane : register(c25),\n"
2713 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2714 "uniform float3 LightPosition : register(c27),\n"
2716 "#ifdef USESHADOWMAPORTHO\n"
2717 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2720 "out float4 gl_FrontColor : COLOR,\n"
2721 "out float4 TexCoordBoth : TEXCOORD0,\n"
2722 "#ifdef USELIGHTMAP\n"
2723 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2725 "#ifdef USEEYEVECTOR\n"
2726 "out float3 EyeVector : TEXCOORD2,\n"
2728 "#ifdef USEREFLECTION\n"
2729 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2732 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2734 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2735 "out float3 LightVector : TEXCOORD1,\n"
2737 "#ifdef MODE_LIGHTSOURCE\n"
2738 "out float3 CubeVector : TEXCOORD3,\n"
2740 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2741 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2742 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2743 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2745 "#ifdef USESHADOWMAPORTHO\n"
2746 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2748 "out float4 gl_Position : POSITION\n"
2751 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2753 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2755 " gl_FrontColor = gl_Color; // Cg is forward\n"
2758 " // copy the surface texcoord\n"
2759 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2760 "#ifdef USEVERTEXTEXTUREBLEND\n"
2761 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2763 "#ifdef USELIGHTMAP\n"
2764 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2767 "#ifdef MODE_LIGHTSOURCE\n"
2768 " // transform vertex position into light attenuation/cubemap space\n"
2769 " // (-1 to +1 across the light box)\n"
2770 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2772 "# ifdef USEDIFFUSE\n"
2773 " // transform unnormalized light direction into tangent space\n"
2774 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2775 " // normalize it per pixel)\n"
2776 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2777 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2778 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2779 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2783 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2784 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2785 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2786 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2789 " // transform unnormalized eye direction into tangent space\n"
2790 "#ifdef USEEYEVECTOR\n"
2791 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2792 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2793 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2794 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2798 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2799 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2802 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2803 " VectorS = gl_MultiTexCoord1.xyz;\n"
2804 " VectorT = gl_MultiTexCoord2.xyz;\n"
2805 " VectorR = gl_MultiTexCoord3.xyz;\n"
2808 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2809 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2811 "#ifdef USESHADOWMAPORTHO\n"
2812 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2815 "#ifdef USEREFLECTION\n"
2816 " ModelViewProjectionPosition = gl_Position;\n"
2819 "#endif // VERTEX_SHADER\n"
2824 "#ifdef FRAGMENT_SHADER\n"
2827 "#ifdef USEDEFERREDLIGHTMAP\n"
2829 "float2 Pixel : VPOS,\n"
2831 "float2 Pixel : WPOS,\n"
2834 "float4 gl_FrontColor : COLOR,\n"
2835 "float4 TexCoordBoth : TEXCOORD0,\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "float2 TexCoordLightmap : TEXCOORD1,\n"
2839 "#ifdef USEEYEVECTOR\n"
2840 "float3 EyeVector : TEXCOORD2,\n"
2842 "#ifdef USEREFLECTION\n"
2843 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2846 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2849 "float3 LightVector : TEXCOORD1,\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "float3 CubeVector : TEXCOORD3,\n"
2854 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2855 "float4 ModelViewPosition : TEXCOORD0,\n"
2857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2858 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2859 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2860 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2862 "#ifdef USESHADOWMAPORTHO\n"
2863 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2866 "uniform sampler Texture_Normal : register(s0),\n"
2867 "uniform sampler Texture_Color : register(s1),\n"
2868 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2869 "uniform sampler Texture_Gloss : register(s2),\n"
2872 "uniform sampler Texture_Glow : register(s3),\n"
2874 "#ifdef USEVERTEXTEXTUREBLEND\n"
2875 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2876 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2877 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2878 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2881 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2884 "#ifdef USECOLORMAPPING\n"
2885 "uniform sampler Texture_Pants : register(s4),\n"
2886 "uniform sampler Texture_Shirt : register(s7),\n"
2889 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2890 "uniform sampler Texture_FogMask : register(s8),\n"
2892 "#ifdef USELIGHTMAP\n"
2893 "uniform sampler Texture_Lightmap : register(s9),\n"
2895 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2896 "uniform sampler Texture_Deluxemap : register(s10),\n"
2898 "#ifdef USEREFLECTION\n"
2899 "uniform sampler Texture_Reflection : register(s7),\n"
2902 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2903 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2904 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2906 "#ifdef USEDEFERREDLIGHTMAP\n"
2907 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2908 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2911 "#ifdef USECOLORMAPPING\n"
2912 "uniform half3 Color_Pants : register(c7),\n"
2913 "uniform half3 Color_Shirt : register(c8),\n"
2916 "uniform float3 FogColor : register(c16),\n"
2917 "uniform float FogRangeRecip : register(c20),\n"
2918 "uniform float FogPlaneViewDist : register(c19),\n"
2919 "uniform float FogHeightFade : register(c17),\n"
2922 "#ifdef USEOFFSETMAPPING\n"
2923 "uniform float OffsetMapping_Scale : register(c24),\n"
2926 "#ifdef USEDEFERREDLIGHTMAP\n"
2927 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2928 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2929 "uniform half3 DeferredMod_Specular : register(c13),\n"
2931 "uniform half3 Color_Ambient : register(c3),\n"
2932 "uniform half3 Color_Diffuse : register(c4),\n"
2933 "uniform half3 Color_Specular : register(c5),\n"
2934 "uniform half SpecularPower : register(c36),\n"
2936 "uniform half3 Color_Glow : register(c6),\n"
2938 "uniform half Alpha : register(c0),\n"
2939 "#ifdef USEREFLECTION\n"
2940 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2941 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2942 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2943 "uniform half4 ReflectColor : register(c26),\n"
2945 "#ifdef USEREFLECTCUBE\n"
2946 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2947 "uniform sampler Texture_ReflectMask : register(s5),\n"
2948 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2950 "#ifdef MODE_LIGHTDIRECTION\n"
2951 "uniform half3 LightColor : register(c21),\n"
2953 "#ifdef MODE_LIGHTSOURCE\n"
2954 "uniform half3 LightColor : register(c21),\n"
2957 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2958 "uniform sampler Texture_Attenuation : register(s9),\n"
2959 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2962 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2964 "#ifdef USESHADOWMAP2D\n"
2965 "# ifdef USESHADOWSAMPLER\n"
2966 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2968 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2972 "#ifdef USESHADOWMAPVSDCT\n"
2973 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2976 "#if defined(USESHADOWMAP2D)\n"
2977 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2978 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2980 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2982 "out float4 gl_FragColor : COLOR\n"
2985 " float2 TexCoord = TexCoordBoth.xy;\n"
2986 "#ifdef USEVERTEXTEXTUREBLEND\n"
2987 " float2 TexCoord2 = TexCoordBoth.zw;\n"
2989 "#ifdef USEOFFSETMAPPING\n"
2990 " // apply offsetmapping\n"
2991 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2992 "#define TexCoord TexCoordOffset\n"
2995 " // combine the diffuse textures (base, pants, shirt)\n"
2996 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2997 "#ifdef USEALPHAKILL\n"
2998 " if (color.a < 0.5)\n"
3001 " color.a *= Alpha;\n"
3002 "#ifdef USECOLORMAPPING\n"
3003 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3005 "#ifdef USEVERTEXTEXTUREBLEND\n"
3006 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3007 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3008 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3009 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3011 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3014 " // get the surface normal\n"
3015 "#ifdef USEVERTEXTEXTUREBLEND\n"
3016 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3018 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3021 " // get the material colors\n"
3022 " half3 diffusetex = color.rgb;\n"
3023 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3024 "# ifdef USEVERTEXTEXTUREBLEND\n"
3025 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3027 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3033 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3034 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3035 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3041 "#ifdef MODE_LIGHTSOURCE\n"
3042 " // light source\n"
3043 "#ifdef USEDIFFUSE\n"
3044 " half3 lightnormal = half3(normalize(LightVector));\n"
3045 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3046 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3047 "#ifdef USESPECULAR\n"
3048 "#ifdef USEEXACTSPECULARMATH\n"
3049 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3051 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3052 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3054 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3057 " color.rgb = diffusetex * Color_Ambient;\n"
3059 " color.rgb *= LightColor;\n"
3060 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3063 "#ifdef USESHADOWMAPVSDCT\n"
3064 ", Texture_CubeProjection\n"
3069 "# ifdef USECUBEFILTER\n"
3070 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3073 "#ifdef USESHADOWMAP2D\n"
3074 "#ifdef USESHADOWMAPVSDCT\n"
3075 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3076 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3077 "// color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3078 "// color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3080 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3081 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3082 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3083 "// color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3084 "// color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3085 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3086 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3087 "// color.r = half(shadowmaptc.z);\n"
3091 "// color.rgb = half3(1,1,1);\n"
3092 "#endif // MODE_LIGHTSOURCE\n"
3097 "#ifdef MODE_LIGHTDIRECTION\n"
3099 "#ifdef USEDIFFUSE\n"
3100 " half3 lightnormal = half3(normalize(LightVector));\n"
3102 "#define lightcolor LightColor\n"
3103 "#endif // MODE_LIGHTDIRECTION\n"
3104 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3106 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3107 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3108 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3109 " // convert modelspace light vector to tangentspace\n"
3110 " half3 lightnormal;\n"
3111 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3112 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3113 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3114 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3115 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3116 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3117 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3118 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3119 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3120 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3121 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3122 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3123 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3124 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3125 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3127 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3128 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3129 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3135 "#ifdef MODE_LIGHTMAP\n"
3136 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3137 "#endif // MODE_LIGHTMAP\n"
3138 "#ifdef MODE_VERTEXCOLOR\n"
3139 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3140 "#endif // MODE_VERTEXCOLOR\n"
3141 "#ifdef MODE_FLATCOLOR\n"
3142 " color.rgb = diffusetex * Color_Ambient;\n"
3143 "#endif // MODE_FLATCOLOR\n"
3149 "# ifdef USEDIFFUSE\n"
3150 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3151 "# ifdef USESPECULAR\n"
3152 "# ifdef USEEXACTSPECULARMATH\n"
3153 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3155 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3156 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3158 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3160 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3163 " color.rgb = diffusetex * Color_Ambient;\n"
3167 "#ifdef USESHADOWMAPORTHO\n"
3168 " color.rgb *= ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale);\n"
3171 "#ifdef USEDEFERREDLIGHTMAP\n"
3172 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3173 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3174 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3178 "#ifdef USEVERTEXTEXTUREBLEND\n"
3179 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3181 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3186 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3189 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3190 "#ifdef USEREFLECTION\n"
3191 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3192 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3193 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3194 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3195 " // FIXME temporary hack to detect the case that the reflection\n"
3196 " // gets blackened at edges due to leaving the area that contains actual\n"
3198 " // Remove this 'ack once we have a better way to stop this thing from\n"
3200 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3201 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3202 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3203 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3204 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3205 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3208 " gl_FragColor = float4(color);\n"
3210 "#endif // FRAGMENT_SHADER\n"
3212 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3213 "#endif // !MODE_DEFERREDGEOMETRY\n"
3214 "#endif // !MODE_WATER\n"
3215 "#endif // !MODE_REFRACTION\n"
3216 "#endif // !MODE_BLOOMBLUR\n"
3217 "#endif // !MODE_GENERIC\n"
3218 "#endif // !MODE_POSTPROCESS\n"
3219 "#endif // !MODE_SHOWDEPTH\n"
3220 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3223 char *glslshaderstring = NULL;
3224 char *cgshaderstring = NULL;
3225 char *hlslshaderstring = NULL;
3227 //=======================================================================================================================================================
3229 typedef struct shaderpermutationinfo_s
3231 const char *pretext;
3234 shaderpermutationinfo_t;
3236 typedef struct shadermodeinfo_s
3238 const char *vertexfilename;
3239 const char *geometryfilename;
3240 const char *fragmentfilename;
3241 const char *pretext;
3246 typedef enum shaderpermutation_e
3248 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3249 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3250 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3251 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3252 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3253 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3254 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3255 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3256 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3257 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3258 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3259 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3260 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3261 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3262 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3263 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3264 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3265 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3266 SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3267 SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3268 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3269 SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3270 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3271 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3272 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3273 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3274 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3275 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3276 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3278 shaderpermutation_t;
3280 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3281 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3283 {"#define USEDIFFUSE\n", " diffuse"},
3284 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3285 {"#define USEVIEWTINT\n", " viewtint"},
3286 {"#define USECOLORMAPPING\n", " colormapping"},
3287 {"#define USESATURATION\n", " saturation"},
3288 {"#define USEFOGINSIDE\n", " foginside"},
3289 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3290 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3291 {"#define USEGAMMARAMPS\n", " gammaramps"},
3292 {"#define USECUBEFILTER\n", " cubefilter"},
3293 {"#define USEGLOW\n", " glow"},
3294 {"#define USEBLOOM\n", " bloom"},
3295 {"#define USESPECULAR\n", " specular"},
3296 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3297 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3298 {"#define USEREFLECTION\n", " reflection"},
3299 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3300 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3301 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3302 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3303 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3304 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3305 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3306 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3307 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3308 {"#define USEALPHAKILL\n", " alphakill"},
3309 {"#define USEREFLECTCUBE\n", " reflectcube"},
3312 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3313 typedef enum shadermode_e
3315 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3316 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3317 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3318 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3319 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3320 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3321 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3322 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3323 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3324 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3325 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3326 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3327 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3328 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3329 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3334 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3335 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3337 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3338 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3339 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3340 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3341 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3342 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3343 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3344 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3345 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3346 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3347 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3348 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3349 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3350 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3351 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3355 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3357 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3358 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3359 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3360 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3361 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3362 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3363 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3364 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3365 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3366 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3367 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3368 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3369 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3370 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3371 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3376 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3378 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3379 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3380 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3381 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3382 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3383 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3384 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3385 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3386 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3387 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3388 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3389 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3390 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3391 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3392 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3396 struct r_glsl_permutation_s;
3397 typedef struct r_glsl_permutation_s
3399 /// hash lookup data
3400 struct r_glsl_permutation_s *hashnext;
3402 unsigned int permutation;
3404 /// indicates if we have tried compiling this permutation already
3406 /// 0 if compilation failed
3408 /// locations of detected uniforms in program object, or -1 if not found
3409 int loc_Texture_First;
3410 int loc_Texture_Second;
3411 int loc_Texture_GammaRamps;
3412 int loc_Texture_Normal;
3413 int loc_Texture_Color;
3414 int loc_Texture_Gloss;
3415 int loc_Texture_Glow;
3416 int loc_Texture_SecondaryNormal;
3417 int loc_Texture_SecondaryColor;
3418 int loc_Texture_SecondaryGloss;
3419 int loc_Texture_SecondaryGlow;
3420 int loc_Texture_Pants;
3421 int loc_Texture_Shirt;
3422 int loc_Texture_FogHeightTexture;
3423 int loc_Texture_FogMask;
3424 int loc_Texture_Lightmap;
3425 int loc_Texture_Deluxemap;
3426 int loc_Texture_Attenuation;
3427 int loc_Texture_Cube;
3428 int loc_Texture_Refraction;
3429 int loc_Texture_Reflection;
3430 int loc_Texture_ShadowMap2D;
3431 int loc_Texture_CubeProjection;
3432 int loc_Texture_ScreenDepth;
3433 int loc_Texture_ScreenNormalMap;
3434 int loc_Texture_ScreenDiffuse;
3435 int loc_Texture_ScreenSpecular;
3436 int loc_Texture_ReflectMask;
3437 int loc_Texture_ReflectCube;
3439 int loc_BloomBlur_Parameters;
3441 int loc_Color_Ambient;
3442 int loc_Color_Diffuse;
3443 int loc_Color_Specular;
3445 int loc_Color_Pants;
3446 int loc_Color_Shirt;
3447 int loc_DeferredColor_Ambient;
3448 int loc_DeferredColor_Diffuse;
3449 int loc_DeferredColor_Specular;
3450 int loc_DeferredMod_Diffuse;
3451 int loc_DeferredMod_Specular;
3452 int loc_DistortScaleRefractReflect;
3453 int loc_EyePosition;
3455 int loc_FogHeightFade;
3457 int loc_FogPlaneViewDist;
3458 int loc_FogRangeRecip;
3461 int loc_LightPosition;
3462 int loc_OffsetMapping_Scale;
3464 int loc_ReflectColor;
3465 int loc_ReflectFactor;
3466 int loc_ReflectOffset;
3467 int loc_RefractColor;
3469 int loc_ScreenCenterRefractReflect;
3470 int loc_ScreenScaleRefractReflect;
3471 int loc_ScreenToDepth;
3472 int loc_ShadowMap_Parameters;
3473 int loc_ShadowMap_TextureScale;
3474 int loc_SpecularPower;
3479 int loc_ViewTintColor;
3480 int loc_ViewToLight;
3481 int loc_ModelToLight;
3483 int loc_BackgroundTexMatrix;
3484 int loc_ModelViewProjectionMatrix;
3485 int loc_ModelViewMatrix;
3486 int loc_PixelToScreenTexCoord;
3487 int loc_ModelToReflectCube;
3488 int loc_ShadowMapMatrix;
3489 int loc_BloomColorSubtract;
3491 r_glsl_permutation_t;
3493 #define SHADERPERMUTATION_HASHSIZE 256
3495 /// information about each possible shader permutation
3496 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3497 /// currently selected permutation
3498 r_glsl_permutation_t *r_glsl_permutation;
3499 /// storage for permutations linked in the hash table
3500 memexpandablearray_t r_glsl_permutationarray;
3502 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3504 //unsigned int hashdepth = 0;
3505 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3506 r_glsl_permutation_t *p;
3507 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3509 if (p->mode == mode && p->permutation == permutation)
3511 //if (hashdepth > 10)
3512 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3517 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3519 p->permutation = permutation;
3520 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3521 r_glsl_permutationhash[mode][hashindex] = p;
3522 //if (hashdepth > 10)
3523 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3527 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3530 if (!filename || !filename[0])
3532 if (!strcmp(filename, "glsl/default.glsl"))
3534 if (!glslshaderstring)
3536 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3537 if (glslshaderstring)
3538 Con_DPrintf("Loading shaders from file %s...\n", filename);
3540 glslshaderstring = (char *)builtinshaderstring;
3542 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3543 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3544 return shaderstring;
3546 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3549 if (printfromdisknotice)
3550 Con_DPrintf("from disk %s... ", filename);
3551 return shaderstring;
3553 return shaderstring;
3556 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3559 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3560 int vertstrings_count = 0;
3561 int geomstrings_count = 0;
3562 int fragstrings_count = 0;
3563 char *vertexstring, *geometrystring, *fragmentstring;
3564 const char *vertstrings_list[32+3];
3565 const char *geomstrings_list[32+3];
3566 const char *fragstrings_list[32+3];
3567 char permutationname[256];
3574 permutationname[0] = 0;
3575 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3576 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3577 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3579 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3581 // the first pretext is which type of shader to compile as
3582 // (later these will all be bound together as a program object)
3583 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3584 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3585 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3587 // the second pretext is the mode (for example a light source)
3588 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3589 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3590 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3591 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3593 // now add all the permutation pretexts
3594 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3596 if (permutation & (1<<i))
3598 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3599 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3600 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3601 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3605 // keep line numbers correct
3606 vertstrings_list[vertstrings_count++] = "\n";
3607 geomstrings_list[geomstrings_count++] = "\n";
3608 fragstrings_list[fragstrings_count++] = "\n";
3612 // now append the shader text itself
3613 vertstrings_list[vertstrings_count++] = vertexstring;
3614 geomstrings_list[geomstrings_count++] = geometrystring;
3615 fragstrings_list[fragstrings_count++] = fragmentstring;
3617 // if any sources were NULL, clear the respective list
3619 vertstrings_count = 0;
3620 if (!geometrystring)
3621 geomstrings_count = 0;
3622 if (!fragmentstring)
3623 fragstrings_count = 0;
3625 // compile the shader program
3626 if (vertstrings_count + geomstrings_count + fragstrings_count)
3627 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3631 qglUseProgramObjectARB(p->program);CHECKGLERROR
3632 // look up all the uniform variable names we care about, so we don't
3633 // have to look them up every time we set them
3635 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3636 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3637 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3638 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3639 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3640 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3641 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3642 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3643 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3644 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3645 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3646 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3647 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3648 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3649 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3650 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3651 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3652 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3653 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3654 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3655 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3656 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3657 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3658 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3659 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3660 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3661 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3662 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3663 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3664 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3665 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3666 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3667 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3668 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3669 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3670 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3671 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3672 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3673 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3674 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3675 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3676 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3677 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3678 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3679 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3680 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3681 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3682 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3683 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3684 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3685 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3686 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3687 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3688 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3689 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3690 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3691 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3692 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3693 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3694 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3695 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3696 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3697 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3698 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3699 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3700 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3701 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3702 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3703 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3704 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3705 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3706 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3707 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3708 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3709 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3710 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3711 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3712 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3713 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3714 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3715 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3716 // initialize the samplers to refer to the texture units we use
3717 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3718 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3719 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3720 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3721 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3722 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3723 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3724 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3725 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3726 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3727 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3728 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3729 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3730 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3731 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3732 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3733 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3734 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3735 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3736 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3737 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3738 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3739 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3740 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3741 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3742 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3743 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3744 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3745 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3747 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3750 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3754 Mem_Free(vertexstring);
3756 Mem_Free(geometrystring);
3758 Mem_Free(fragmentstring);
3761 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3763 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3764 if (r_glsl_permutation != perm)
3766 r_glsl_permutation = perm;
3767 if (!r_glsl_permutation->program)
3769 if (!r_glsl_permutation->compiled)
3770 R_GLSL_CompilePermutation(perm, mode, permutation);
3771 if (!r_glsl_permutation->program)
3773 // remove features until we find a valid permutation
3775 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3777 // reduce i more quickly whenever it would not remove any bits
3778 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3779 if (!(permutation & j))
3782 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3783 if (!r_glsl_permutation->compiled)
3784 R_GLSL_CompilePermutation(perm, mode, permutation);
3785 if (r_glsl_permutation->program)
3788 if (i >= SHADERPERMUTATION_COUNT)
3790 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3791 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3792 qglUseProgramObjectARB(0);CHECKGLERROR
3793 return; // no bit left to clear, entire mode is broken
3798 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3800 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3801 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3802 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3806 #include <Cg/cgGL.h>
3807 struct r_cg_permutation_s;
3808 typedef struct r_cg_permutation_s
3810 /// hash lookup data
3811 struct r_cg_permutation_s *hashnext;
3813 unsigned int permutation;
3815 /// indicates if we have tried compiling this permutation already
3817 /// 0 if compilation failed
3820 /// locations of detected parameters in programs, or NULL if not found
3821 CGparameter vp_EyePosition;
3822 CGparameter vp_FogPlane;
3823 CGparameter vp_LightDir;
3824 CGparameter vp_LightPosition;
3825 CGparameter vp_ModelToLight;
3826 CGparameter vp_TexMatrix;
3827 CGparameter vp_BackgroundTexMatrix;
3828 CGparameter vp_ModelViewProjectionMatrix;
3829 CGparameter vp_ModelViewMatrix;
3830 CGparameter vp_ShadowMapMatrix;
3832 CGparameter fp_Texture_First;
3833 CGparameter fp_Texture_Second;
3834 CGparameter fp_Texture_GammaRamps;
3835 CGparameter fp_Texture_Normal;
3836 CGparameter fp_Texture_Color;
3837 CGparameter fp_Texture_Gloss;
3838 CGparameter fp_Texture_Glow;
3839 CGparameter fp_Texture_SecondaryNormal;
3840 CGparameter fp_Texture_SecondaryColor;
3841 CGparameter fp_Texture_SecondaryGloss;
3842 CGparameter fp_Texture_SecondaryGlow;
3843 CGparameter fp_Texture_Pants;
3844 CGparameter fp_Texture_Shirt;
3845 CGparameter fp_Texture_FogHeightTexture;
3846 CGparameter fp_Texture_FogMask;
3847 CGparameter fp_Texture_Lightmap;
3848 CGparameter fp_Texture_Deluxemap;
3849 CGparameter fp_Texture_Attenuation;
3850 CGparameter fp_Texture_Cube;
3851 CGparameter fp_Texture_Refraction;
3852 CGparameter fp_Texture_Reflection;
3853 CGparameter fp_Texture_ShadowMap2D;
3854 CGparameter fp_Texture_CubeProjection;
3855 CGparameter fp_Texture_ScreenDepth;
3856 CGparameter fp_Texture_ScreenNormalMap;
3857 CGparameter fp_Texture_ScreenDiffuse;
3858 CGparameter fp_Texture_ScreenSpecular;
3859 CGparameter fp_Texture_ReflectMask;
3860 CGparameter fp_Texture_ReflectCube;
3861 CGparameter fp_Alpha;
3862 CGparameter fp_BloomBlur_Parameters;
3863 CGparameter fp_ClientTime;
3864 CGparameter fp_Color_Ambient;
3865 CGparameter fp_Color_Diffuse;
3866 CGparameter fp_Color_Specular;
3867 CGparameter fp_Color_Glow;
3868 CGparameter fp_Color_Pants;
3869 CGparameter fp_Color_Shirt;
3870 CGparameter fp_DeferredColor_Ambient;
3871 CGparameter fp_DeferredColor_Diffuse;
3872 CGparameter fp_DeferredColor_Specular;
3873 CGparameter fp_DeferredMod_Diffuse;
3874 CGparameter fp_DeferredMod_Specular;
3875 CGparameter fp_DistortScaleRefractReflect;
3876 CGparameter fp_EyePosition;
3877 CGparameter fp_FogColor;
3878 CGparameter fp_FogHeightFade;
3879 CGparameter fp_FogPlane;
3880 CGparameter fp_FogPlaneViewDist;
3881 CGparameter fp_FogRangeRecip;
3882 CGparameter fp_LightColor;
3883 CGparameter fp_LightDir;
3884 CGparameter fp_LightPosition;
3885 CGparameter fp_OffsetMapping_Scale;
3886 CGparameter fp_PixelSize;
3887 CGparameter fp_ReflectColor;
3888 CGparameter fp_ReflectFactor;
3889 CGparameter fp_ReflectOffset;
3890 CGparameter fp_RefractColor;
3891 CGparameter fp_Saturation;
3892 CGparameter fp_ScreenCenterRefractReflect;
3893 CGparameter fp_ScreenScaleRefractReflect;
3894 CGparameter fp_ScreenToDepth;
3895 CGparameter fp_ShadowMap_Parameters;
3896 CGparameter fp_ShadowMap_TextureScale;
3897 CGparameter fp_SpecularPower;
3898 CGparameter fp_UserVec1;
3899 CGparameter fp_UserVec2;
3900 CGparameter fp_UserVec3;
3901 CGparameter fp_UserVec4;
3902 CGparameter fp_ViewTintColor;
3903 CGparameter fp_ViewToLight;
3904 CGparameter fp_PixelToScreenTexCoord;
3905 CGparameter fp_ModelToReflectCube;
3906 CGparameter fp_BloomColorSubtract;
3910 /// information about each possible shader permutation
3911 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3912 /// currently selected permutation
3913 r_cg_permutation_t *r_cg_permutation;
3914 /// storage for permutations linked in the hash table
3915 memexpandablearray_t r_cg_permutationarray;
3917 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3919 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3921 //unsigned int hashdepth = 0;
3922 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3923 r_cg_permutation_t *p;
3924 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3926 if (p->mode == mode && p->permutation == permutation)
3928 //if (hashdepth > 10)
3929 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3934 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3936 p->permutation = permutation;
3937 p->hashnext = r_cg_permutationhash[mode][hashindex];
3938 r_cg_permutationhash[mode][hashindex] = p;
3939 //if (hashdepth > 10)
3940 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3944 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3947 if (!filename || !filename[0])
3949 if (!strcmp(filename, "cg/default.cg"))
3951 if (!cgshaderstring)
3953 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3955 Con_DPrintf("Loading shaders from file %s...\n", filename);
3957 cgshaderstring = (char *)builtincgshaderstring;
3959 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3960 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3961 return shaderstring;
3963 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3966 if (printfromdisknotice)
3967 Con_DPrintf("from disk %s... ", filename);
3968 return shaderstring;
3970 return shaderstring;
3973 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3975 // TODO: load or create .fp and .vp shader files
3978 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3981 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3982 int vertstrings_count = 0, vertstring_length = 0;
3983 int geomstrings_count = 0, geomstring_length = 0;
3984 int fragstrings_count = 0, fragstring_length = 0;
3986 char *vertexstring, *geometrystring, *fragmentstring;
3987 char *vertstring, *geomstring, *fragstring;
3988 const char *vertstrings_list[32+3];
3989 const char *geomstrings_list[32+3];
3990 const char *fragstrings_list[32+3];
3991 char permutationname[256];
3992 char cachename[256];
3993 CGprofile vertexProfile;
3994 CGprofile fragmentProfile;
4002 permutationname[0] = 0;
4004 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4005 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4006 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4008 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4009 strlcat(cachename, "cg/", sizeof(cachename));
4011 // the first pretext is which type of shader to compile as
4012 // (later these will all be bound together as a program object)
4013 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4014 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4015 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4017 // the second pretext is the mode (for example a light source)
4018 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4019 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4020 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4021 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4022 strlcat(cachename, modeinfo->name, sizeof(cachename));
4024 // now add all the permutation pretexts
4025 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4027 if (permutation & (1<<i))
4029 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4030 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4031 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4032 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4033 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4037 // keep line numbers correct
4038 vertstrings_list[vertstrings_count++] = "\n";
4039 geomstrings_list[geomstrings_count++] = "\n";
4040 fragstrings_list[fragstrings_count++] = "\n";
4044 // replace spaces in the cachename with _ characters
4045 for (i = 0;cachename[i];i++)
4046 if (cachename[i] == ' ')
4049 // now append the shader text itself
4050 vertstrings_list[vertstrings_count++] = vertexstring;
4051 geomstrings_list[geomstrings_count++] = geometrystring;
4052 fragstrings_list[fragstrings_count++] = fragmentstring;
4054 // if any sources were NULL, clear the respective list
4056 vertstrings_count = 0;
4057 if (!geometrystring)
4058 geomstrings_count = 0;
4059 if (!fragmentstring)
4060 fragstrings_count = 0;
4062 vertstring_length = 0;
4063 for (i = 0;i < vertstrings_count;i++)
4064 vertstring_length += strlen(vertstrings_list[i]);
4065 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4066 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4067 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4069 geomstring_length = 0;
4070 for (i = 0;i < geomstrings_count;i++)
4071 geomstring_length += strlen(geomstrings_list[i]);
4072 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4073 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4074 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4076 fragstring_length = 0;
4077 for (i = 0;i < fragstrings_count;i++)
4078 fragstring_length += strlen(fragstrings_list[i]);
4079 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4080 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4081 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4085 //vertexProfile = CG_PROFILE_ARBVP1;
4086 //fragmentProfile = CG_PROFILE_ARBFP1;
4087 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4088 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4089 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4090 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4091 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4094 // try to load the cached shader, or generate one
4095 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4097 // if caching failed, do a dynamic compile for now
4099 if (vertstring[0] && !p->vprogram)
4100 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4102 if (fragstring[0] && !p->fprogram)
4103 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4106 // look up all the uniform variable names we care about, so we don't
4107 // have to look them up every time we set them
4111 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4112 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4113 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4114 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4115 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4116 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4117 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4118 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4119 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4120 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4121 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4122 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4128 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4129 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4130 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4131 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4132 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4133 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4134 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4135 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4136 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4137 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4138 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4139 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4140 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4141 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4142 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4143 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4144 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4145 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4146 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4147 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4148 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4149 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4150 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4151 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4152 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4153 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4154 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4155 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4156 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4157 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4158 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4159 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4160 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4161 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4162 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4163 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4164 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4165 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4166 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4167 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4168 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4169 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4170 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4171 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4172 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4173 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4174 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4175 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4176 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4177 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4178 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4179 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4180 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4181 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4182 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4183 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4184 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4185 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4186 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4187 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4188 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4189 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4190 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4191 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4192 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4193 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4194 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4195 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4196 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4197 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4198 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4199 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4200 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4201 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4202 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4203 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4204 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4208 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4209 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4211 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4215 Mem_Free(vertstring);
4217 Mem_Free(geomstring);
4219 Mem_Free(fragstring);
4221 Mem_Free(vertexstring);
4223 Mem_Free(geometrystring);
4225 Mem_Free(fragmentstring);
4228 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4230 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4233 if (r_cg_permutation != perm)
4235 r_cg_permutation = perm;
4236 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4238 if (!r_cg_permutation->compiled)
4239 R_CG_CompilePermutation(perm, mode, permutation);
4240 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4242 // remove features until we find a valid permutation
4244 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4246 // reduce i more quickly whenever it would not remove any bits
4247 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4248 if (!(permutation & j))
4251 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4252 if (!r_cg_permutation->compiled)
4253 R_CG_CompilePermutation(perm, mode, permutation);
4254 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4257 if (i >= SHADERPERMUTATION_COUNT)
4259 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4260 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4261 return; // no bit left to clear, entire mode is broken
4267 if (r_cg_permutation->vprogram)
4269 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4270 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4271 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4275 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4276 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4278 if (r_cg_permutation->fprogram)
4280 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4281 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4282 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4286 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4287 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4291 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4292 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4293 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4296 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4298 cgGLSetTextureParameter(param, R_GetTexture(tex));
4299 cgGLEnableTextureParameter(param);
4307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4308 extern D3DCAPS9 vid_d3d9caps;
4311 struct r_hlsl_permutation_s;
4312 typedef struct r_hlsl_permutation_s
4314 /// hash lookup data
4315 struct r_hlsl_permutation_s *hashnext;
4317 unsigned int permutation;
4319 /// indicates if we have tried compiling this permutation already
4321 /// NULL if compilation failed
4322 IDirect3DVertexShader9 *vertexshader;
4323 IDirect3DPixelShader9 *pixelshader;
4325 r_hlsl_permutation_t;
4327 typedef enum D3DVSREGISTER_e
4329 D3DVSREGISTER_TexMatrix = 0, // float4x4
4330 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4331 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4332 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4333 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4334 D3DVSREGISTER_ModelToLight = 20, // float4x4
4335 D3DVSREGISTER_EyePosition = 24,
4336 D3DVSREGISTER_FogPlane = 25,
4337 D3DVSREGISTER_LightDir = 26,
4338 D3DVSREGISTER_LightPosition = 27,
4342 typedef enum D3DPSREGISTER_e
4344 D3DPSREGISTER_Alpha = 0,
4345 D3DPSREGISTER_BloomBlur_Parameters = 1,
4346 D3DPSREGISTER_ClientTime = 2,
4347 D3DPSREGISTER_Color_Ambient = 3,
4348 D3DPSREGISTER_Color_Diffuse = 4,
4349 D3DPSREGISTER_Color_Specular = 5,
4350 D3DPSREGISTER_Color_Glow = 6,
4351 D3DPSREGISTER_Color_Pants = 7,
4352 D3DPSREGISTER_Color_Shirt = 8,
4353 D3DPSREGISTER_DeferredColor_Ambient = 9,
4354 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4355 D3DPSREGISTER_DeferredColor_Specular = 11,
4356 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4357 D3DPSREGISTER_DeferredMod_Specular = 13,
4358 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4359 D3DPSREGISTER_EyePosition = 15, // unused
4360 D3DPSREGISTER_FogColor = 16,
4361 D3DPSREGISTER_FogHeightFade = 17,
4362 D3DPSREGISTER_FogPlane = 18,
4363 D3DPSREGISTER_FogPlaneViewDist = 19,
4364 D3DPSREGISTER_FogRangeRecip = 20,
4365 D3DPSREGISTER_LightColor = 21,
4366 D3DPSREGISTER_LightDir = 22, // unused
4367 D3DPSREGISTER_LightPosition = 23,
4368 D3DPSREGISTER_OffsetMapping_Scale = 24,
4369 D3DPSREGISTER_PixelSize = 25,
4370 D3DPSREGISTER_ReflectColor = 26,
4371 D3DPSREGISTER_ReflectFactor = 27,
4372 D3DPSREGISTER_ReflectOffset = 28,
4373 D3DPSREGISTER_RefractColor = 29,
4374 D3DPSREGISTER_Saturation = 30,
4375 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4376 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4377 D3DPSREGISTER_ScreenToDepth = 33,
4378 D3DPSREGISTER_ShadowMap_Parameters = 34,
4379 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4380 D3DPSREGISTER_SpecularPower = 36,
4381 D3DPSREGISTER_UserVec1 = 37,
4382 D3DPSREGISTER_UserVec2 = 38,
4383 D3DPSREGISTER_UserVec3 = 39,
4384 D3DPSREGISTER_UserVec4 = 40,
4385 D3DPSREGISTER_ViewTintColor = 41,
4386 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4387 D3DPSREGISTER_BloomColorSubtract = 43,
4388 D3DPSREGISTER_ViewToLight = 44, // float4x4
4389 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4394 /// information about each possible shader permutation
4395 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4396 /// currently selected permutation
4397 r_hlsl_permutation_t *r_hlsl_permutation;
4398 /// storage for permutations linked in the hash table
4399 memexpandablearray_t r_hlsl_permutationarray;
4401 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4403 //unsigned int hashdepth = 0;
4404 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4405 r_hlsl_permutation_t *p;
4406 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4408 if (p->mode == mode && p->permutation == permutation)
4410 //if (hashdepth > 10)
4411 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4416 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4418 p->permutation = permutation;
4419 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4420 r_hlsl_permutationhash[mode][hashindex] = p;
4421 //if (hashdepth > 10)
4422 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4426 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4429 if (!filename || !filename[0])
4431 if (!strcmp(filename, "hlsl/default.hlsl"))
4433 if (!hlslshaderstring)
4435 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4436 if (hlslshaderstring)
4437 Con_DPrintf("Loading shaders from file %s...\n", filename);
4439 hlslshaderstring = (char *)builtincgshaderstring;
4441 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4442 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4443 return shaderstring;
4445 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4448 if (printfromdisknotice)
4449 Con_DPrintf("from disk %s... ", filename);
4450 return shaderstring;
4452 return shaderstring;
4456 //#include <d3dx9shader.h>
4457 //#include <d3dx9mesh.h>
4459 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4461 DWORD *vsbin = NULL;
4462 DWORD *psbin = NULL;
4463 fs_offset_t vsbinsize;
4464 fs_offset_t psbinsize;
4465 // IDirect3DVertexShader9 *vs = NULL;
4466 // IDirect3DPixelShader9 *ps = NULL;
4467 ID3DXBuffer *vslog = NULL;
4468 ID3DXBuffer *vsbuffer = NULL;
4469 ID3DXConstantTable *vsconstanttable = NULL;
4470 ID3DXBuffer *pslog = NULL;
4471 ID3DXBuffer *psbuffer = NULL;
4472 ID3DXConstantTable *psconstanttable = NULL;
4475 char temp[MAX_INPUTLINE];
4476 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4477 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4478 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4479 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4480 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4481 if ((!vsbin && vertstring) || (!psbin && fragstring))
4483 const char* dllnames_d3dx9 [] =
4507 dllhandle_t d3dx9_dll = NULL;
4508 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4509 // HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4510 dllfunction_t d3dx9_dllfuncs[] =
4512 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4513 // {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4516 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4518 DWORD shaderflags = 0;
4519 // shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4520 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4521 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4522 if (vertstring && vertstring[0])
4524 // FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4525 // vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4529 vsbinsize = vsbuffer->GetBufferSize();
4530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4532 vsbuffer->Release();
4536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4541 if (fragstring && fragstring[0])
4543 // FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4544 // psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4545 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4548 psbinsize = psbuffer->GetBufferSize();
4549 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4550 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4551 psbuffer->Release();
4555 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4556 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4560 Sys_UnloadLibrary(&d3dx9_dll);
4563 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4567 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4568 if (FAILED(vsresult))
4569 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4573 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4574 if (FAILED(psresult))
4575 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4577 // free the shader data
4578 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4579 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4582 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4585 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4586 int vertstrings_count = 0, vertstring_length = 0;
4587 int geomstrings_count = 0, geomstring_length = 0;
4588 int fragstrings_count = 0, fragstring_length = 0;
4590 char *vertexstring, *geometrystring, *fragmentstring;
4591 char *vertstring, *geomstring, *fragstring;
4592 const char *vertstrings_list[32+3];
4593 const char *geomstrings_list[32+3];
4594 const char *fragstrings_list[32+3];
4595 char permutationname[256];
4596 char cachename[256];
4601 p->vertexshader = NULL;
4602 p->pixelshader = NULL;
4604 permutationname[0] = 0;
4606 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4607 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4608 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4610 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4611 strlcat(cachename, "hlsl/", sizeof(cachename));
4613 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4614 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4615 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4616 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4618 // the first pretext is which type of shader to compile as
4619 // (later these will all be bound together as a program object)
4620 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4621 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4622 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4624 // the second pretext is the mode (for example a light source)
4625 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4626 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4627 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4628 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4629 strlcat(cachename, modeinfo->name, sizeof(cachename));
4631 // now add all the permutation pretexts
4632 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4634 if (permutation & (1<<i))
4636 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4637 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4638 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4639 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4640 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4644 // keep line numbers correct
4645 vertstrings_list[vertstrings_count++] = "\n";
4646 geomstrings_list[geomstrings_count++] = "\n";
4647 fragstrings_list[fragstrings_count++] = "\n";
4651 // replace spaces in the cachename with _ characters
4652 for (i = 0;cachename[i];i++)
4653 if (cachename[i] == ' ')
4656 // now append the shader text itself
4657 vertstrings_list[vertstrings_count++] = vertexstring;
4658 geomstrings_list[geomstrings_count++] = geometrystring;
4659 fragstrings_list[fragstrings_count++] = fragmentstring;
4661 // if any sources were NULL, clear the respective list
4663 vertstrings_count = 0;
4664 if (!geometrystring)
4665 geomstrings_count = 0;
4666 if (!fragmentstring)
4667 fragstrings_count = 0;
4669 vertstring_length = 0;
4670 for (i = 0;i < vertstrings_count;i++)
4671 vertstring_length += strlen(vertstrings_list[i]);
4672 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4673 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4674 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4676 geomstring_length = 0;
4677 for (i = 0;i < geomstrings_count;i++)
4678 geomstring_length += strlen(geomstrings_list[i]);
4679 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4680 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4681 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4683 fragstring_length = 0;
4684 for (i = 0;i < fragstrings_count;i++)
4685 fragstring_length += strlen(fragstrings_list[i]);
4686 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4687 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4688 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4690 // try to load the cached shader, or generate one
4691 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4693 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4694 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4696 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4700 Mem_Free(vertstring);
4702 Mem_Free(geomstring);
4704 Mem_Free(fragstring);
4706 Mem_Free(vertexstring);
4708 Mem_Free(geometrystring);
4710 Mem_Free(fragmentstring);
4713 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4714 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4715 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);}
4716 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);}
4717 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);}
4718 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);}
4720 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4721 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4722 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);}
4723 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);}
4724 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);}
4725 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);}
4727 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4729 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4730 if (r_hlsl_permutation != perm)
4732 r_hlsl_permutation = perm;
4733 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4735 if (!r_hlsl_permutation->compiled)
4736 R_HLSL_CompilePermutation(perm, mode, permutation);
4737 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4739 // remove features until we find a valid permutation
4741 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4743 // reduce i more quickly whenever it would not remove any bits
4744 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4745 if (!(permutation & j))
4748 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4749 if (!r_hlsl_permutation->compiled)
4750 R_HLSL_CompilePermutation(perm, mode, permutation);
4751 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4754 if (i >= SHADERPERMUTATION_COUNT)
4756 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4757 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4758 return; // no bit left to clear, entire mode is broken
4762 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4763 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4765 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4766 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4767 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4771 void R_GLSL_Restart_f(void)
4773 unsigned int i, limit;
4774 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4775 Mem_Free(glslshaderstring);
4776 glslshaderstring = NULL;
4777 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4778 Mem_Free(cgshaderstring);
4779 cgshaderstring = NULL;
4780 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4781 Mem_Free(hlslshaderstring);
4782 hlslshaderstring = NULL;
4783 switch(vid.renderpath)
4785 case RENDERPATH_D3D9:
4788 r_hlsl_permutation_t *p;
4789 r_hlsl_permutation = NULL;
4790 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4791 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4792 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4793 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4794 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4795 for (i = 0;i < limit;i++)
4797 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4799 if (p->vertexshader)
4800 IDirect3DVertexShader9_Release(p->vertexshader);
4802 IDirect3DPixelShader9_Release(p->pixelshader);
4803 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4806 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4810 case RENDERPATH_D3D10:
4811 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4813 case RENDERPATH_D3D11:
4814 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4816 case RENDERPATH_GL20:
4818 r_glsl_permutation_t *p;
4819 r_glsl_permutation = NULL;
4820 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4821 for (i = 0;i < limit;i++)
4823 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4825 GL_Backend_FreeProgram(p->program);
4826 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4829 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4832 case RENDERPATH_CGGL:
4835 r_cg_permutation_t *p;
4836 r_cg_permutation = NULL;
4837 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4838 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4839 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4840 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4841 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4842 for (i = 0;i < limit;i++)
4844 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4847 cgDestroyProgram(p->vprogram);
4849 cgDestroyProgram(p->fprogram);
4850 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4853 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4857 case RENDERPATH_GL13:
4858 case RENDERPATH_GL11:
4863 void R_GLSL_DumpShader_f(void)
4868 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4871 FS_Print(file, "/* The engine may define the following macros:\n");
4872 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4873 for (i = 0;i < SHADERMODE_COUNT;i++)
4874 FS_Print(file, glslshadermodeinfo[i].pretext);
4875 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4876 FS_Print(file, shaderpermutationinfo[i].pretext);
4877 FS_Print(file, "*/\n");
4878 FS_Print(file, builtinshaderstring);
4880 Con_Printf("glsl/default.glsl written\n");
4883 Con_Printf("failed to write to glsl/default.glsl\n");
4886 file = FS_OpenRealFile("cg/default.cg", "w", false);
4889 FS_Print(file, "/* The engine may define the following macros:\n");
4890 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4891 for (i = 0;i < SHADERMODE_COUNT;i++)
4892 FS_Print(file, cgshadermodeinfo[i].pretext);
4893 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4894 FS_Print(file, shaderpermutationinfo[i].pretext);
4895 FS_Print(file, "*/\n");
4896 FS_Print(file, builtincgshaderstring);
4898 Con_Printf("cg/default.cg written\n");
4901 Con_Printf("failed to write to cg/default.cg\n");
4905 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4908 FS_Print(file, "/* The engine may define the following macros:\n");
4909 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4910 for (i = 0;i < SHADERMODE_COUNT;i++)
4911 FS_Print(file, hlslshadermodeinfo[i].pretext);
4912 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4913 FS_Print(file, shaderpermutationinfo[i].pretext);
4914 FS_Print(file, "*/\n");
4915 FS_Print(file, builtincgshaderstring);
4917 Con_Printf("hlsl/default.hlsl written\n");
4920 Con_Printf("failed to write to hlsl/default.hlsl\n");
4924 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4927 texturemode = GL_MODULATE;
4928 switch (vid.renderpath)
4930 case RENDERPATH_D3D9:
4932 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))));
4933 R_Mesh_TexBind(GL20TU_FIRST , first );
4934 R_Mesh_TexBind(GL20TU_SECOND, second);
4937 case RENDERPATH_D3D10:
4938 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4940 case RENDERPATH_D3D11:
4941 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4943 case RENDERPATH_GL20:
4944 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))));
4945 R_Mesh_TexBind(GL20TU_FIRST , first );
4946 R_Mesh_TexBind(GL20TU_SECOND, second);
4948 case RENDERPATH_CGGL:
4951 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))));
4952 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4953 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4956 case RENDERPATH_GL13:
4957 R_Mesh_TexBind(0, first );
4958 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4959 R_Mesh_TexBind(1, second);
4961 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4963 case RENDERPATH_GL11:
4964 R_Mesh_TexBind(0, first );
4969 void R_SetupShader_DepthOrShadow(void)
4971 switch (vid.renderpath)
4973 case RENDERPATH_D3D9:
4975 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4978 case RENDERPATH_D3D10:
4979 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4981 case RENDERPATH_D3D11:
4982 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4984 case RENDERPATH_GL20:
4985 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4987 case RENDERPATH_CGGL:
4989 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4992 case RENDERPATH_GL13:
4993 R_Mesh_TexBind(0, 0);
4994 R_Mesh_TexBind(1, 0);
4996 case RENDERPATH_GL11:
4997 R_Mesh_TexBind(0, 0);
5002 void R_SetupShader_ShowDepth(void)
5004 switch (vid.renderpath)
5006 case RENDERPATH_D3D9:
5008 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5011 case RENDERPATH_D3D10:
5012 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5014 case RENDERPATH_D3D11:
5015 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5017 case RENDERPATH_GL20:
5018 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5020 case RENDERPATH_CGGL:
5022 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5025 case RENDERPATH_GL13:
5027 case RENDERPATH_GL11:
5032 extern qboolean r_shadow_usingdeferredprepass;
5033 extern cvar_t r_shadow_deferred_8bitrange;
5034 extern rtexture_t *r_shadow_attenuationgradienttexture;
5035 extern rtexture_t *r_shadow_attenuation2dtexture;
5036 extern rtexture_t *r_shadow_attenuation3dtexture;
5037 extern qboolean r_shadow_usingshadowmap2d;
5038 extern qboolean r_shadow_usingshadowmaportho;
5039 extern float r_shadow_shadowmap_texturescale[2];
5040 extern float r_shadow_shadowmap_parameters[4];
5041 extern qboolean r_shadow_shadowmapvsdct;
5042 extern qboolean r_shadow_shadowmapsampler;
5043 extern int r_shadow_shadowmappcf;
5044 extern rtexture_t *r_shadow_shadowmap2dtexture;
5045 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5046 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5047 extern matrix4x4_t r_shadow_shadowmapmatrix;
5048 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5049 extern int r_shadow_prepass_width;
5050 extern int r_shadow_prepass_height;
5051 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5052 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5053 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5054 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5055 extern cvar_t gl_mesh_separatearrays;
5056 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5058 // a blendfunc allows colormod if:
5059 // a) it can never keep the destination pixel invariant, or
5060 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5061 // this is to prevent unintended side effects from colormod
5064 // IF there is a (s, sa) for which for all (d, da),
5065 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5066 // THEN, for this (s, sa) and all (colormod, d, da):
5067 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5068 // OBVIOUSLY, this means that
5069 // s*colormod * src(s*colormod, d, sa, da) = 0
5070 // dst(s*colormod, d, sa, da) = 1
5072 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5074 // main condition to leave dst color invariant:
5075 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5077 // s * 0 + d * dst(s, d, sa, da) == d
5078 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5079 // => colormod is a problem for GL_SRC_COLOR only
5081 // s + d * dst(s, d, sa, da) == d
5083 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5084 // => colormod is never problematic for these
5085 // src == GL_SRC_COLOR:
5086 // s*s + d * dst(s, d, sa, da) == d
5088 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5089 // => colormod is never problematic for these
5090 // src == GL_ONE_MINUS_SRC_COLOR:
5091 // s*(1-s) + d * dst(s, d, sa, da) == d
5092 // => s == 0 or s == 1
5093 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5094 // => colormod is a problem for GL_SRC_COLOR only
5095 // src == GL_DST_COLOR
5096 // s*d + d * dst(s, d, sa, da) == d
5098 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5099 // => colormod is always a problem
5102 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5103 // => colormod is never problematic for these
5104 // => BUT, we do not know s! We must assume it is problematic
5105 // then... except in GL_ONE case, where we know all invariant
5107 // src == GL_ONE_MINUS_DST_COLOR
5108 // s*(1-d) + d * dst(s, d, sa, da) == d
5109 // => s == 0 (1-d is impossible to handle for our desired result)
5110 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5111 // => colormod is never problematic for these
5112 // src == GL_SRC_ALPHA
5113 // s*sa + d * dst(s, d, sa, da) == d
5114 // => s == 0, or sa == 0
5115 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5116 // => colormod breaks in the case GL_SRC_COLOR only
5117 // src == GL_ONE_MINUS_SRC_ALPHA
5118 // s*(1-sa) + d * dst(s, d, sa, da) == d
5119 // => s == 0, or sa == 1
5120 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5121 // => colormod breaks in the case GL_SRC_COLOR only
5122 // src == GL_DST_ALPHA
5123 // s*da + d * dst(s, d, sa, da) == d
5125 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5126 // => colormod is never problematic for these
5131 case GL_ONE_MINUS_SRC_COLOR:
5133 case GL_ONE_MINUS_SRC_ALPHA:
5134 if(dst == GL_SRC_COLOR)
5139 case GL_ONE_MINUS_DST_COLOR:
5141 case GL_ONE_MINUS_DST_ALPHA:
5151 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)
5153 // select a permutation of the lighting shader appropriate to this
5154 // combination of texture, entity, light source, and fogging, only use the
5155 // minimum features necessary to avoid wasting rendering time in the
5156 // fragment shader on features that are not being used
5157 unsigned int permutation = 0;
5158 unsigned int mode = 0;
5159 qboolean allow_colormod;
5160 static float dummy_colormod[3] = {1, 1, 1};
5161 float *colormod = rsurface.colormod;
5163 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5164 if (rsurfacepass == RSURFPASS_BACKGROUND)
5166 // distorted background
5167 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5168 mode = SHADERMODE_WATER;
5169 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5170 mode = SHADERMODE_REFRACTION;
5173 mode = SHADERMODE_GENERIC;
5174 permutation |= SHADERPERMUTATION_DIFFUSE;
5176 GL_AlphaTest(false);
5177 GL_BlendFunc(GL_ONE, GL_ZERO);
5178 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5180 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5182 if (r_glsl_offsetmapping.integer)
5184 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5185 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5186 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5187 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5188 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5190 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5191 if (r_glsl_offsetmapping_reliefmapping.integer)
5192 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5195 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5196 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5197 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5198 permutation |= SHADERPERMUTATION_ALPHAKILL;
5199 // normalmap (deferred prepass), may use alpha test on diffuse
5200 mode = SHADERMODE_DEFERREDGEOMETRY;
5201 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5202 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5203 GL_AlphaTest(false);
5204 GL_BlendFunc(GL_ONE, GL_ZERO);
5205 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5207 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5209 if (r_glsl_offsetmapping.integer)
5211 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5212 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5213 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5214 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5215 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5217 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5218 if (r_glsl_offsetmapping_reliefmapping.integer)
5219 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5222 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5223 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5225 mode = SHADERMODE_LIGHTSOURCE;
5226 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5227 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5228 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5229 permutation |= SHADERPERMUTATION_CUBEFILTER;
5230 if (diffusescale > 0)
5231 permutation |= SHADERPERMUTATION_DIFFUSE;
5232 if (specularscale > 0)
5234 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5235 if (r_shadow_glossexact.integer)
5236 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5238 if (r_refdef.fogenabled)
5239 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5240 if (rsurface.texture->colormapping)
5241 permutation |= SHADERPERMUTATION_COLORMAPPING;
5242 if (r_shadow_usingshadowmap2d)
5244 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5245 if(r_shadow_shadowmapvsdct)
5246 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5248 if (r_shadow_shadowmapsampler)
5249 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5250 if (r_shadow_shadowmappcf > 1)
5251 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5252 else if (r_shadow_shadowmappcf)
5253 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5255 if (rsurface.texture->reflectmasktexture)
5256 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5257 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5258 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5259 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5261 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5263 if (r_glsl_offsetmapping.integer)
5265 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5266 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5267 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5268 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5269 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5271 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5272 if (r_glsl_offsetmapping_reliefmapping.integer)
5273 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5276 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5277 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5278 // unshaded geometry (fullbright or ambient model lighting)
5279 mode = SHADERMODE_FLATCOLOR;
5280 ambientscale = diffusescale = specularscale = 0;
5281 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5282 permutation |= SHADERPERMUTATION_GLOW;
5283 if (r_refdef.fogenabled)
5284 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5285 if (rsurface.texture->colormapping)
5286 permutation |= SHADERPERMUTATION_COLORMAPPING;
5287 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5289 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5290 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5292 if (r_shadow_shadowmapsampler)
5293 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5294 if (r_shadow_shadowmappcf > 1)
5295 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5296 else if (r_shadow_shadowmappcf)
5297 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5299 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5300 permutation |= SHADERPERMUTATION_REFLECTION;
5301 if (rsurface.texture->reflectmasktexture)
5302 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5303 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5304 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5305 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5307 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5309 if (r_glsl_offsetmapping.integer)
5311 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5312 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5313 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5314 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5315 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5317 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5318 if (r_glsl_offsetmapping_reliefmapping.integer)
5319 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5323 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5324 // directional model lighting
5325 mode = SHADERMODE_LIGHTDIRECTION;
5326 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5327 permutation |= SHADERPERMUTATION_GLOW;
5328 permutation |= SHADERPERMUTATION_DIFFUSE;
5329 if (specularscale > 0)
5331 permutation |= SHADERPERMUTATION_SPECULAR;
5332 if (r_shadow_glossexact.integer)
5333 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5335 if (r_refdef.fogenabled)
5336 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5337 if (rsurface.texture->colormapping)
5338 permutation |= SHADERPERMUTATION_COLORMAPPING;
5339 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5341 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5342 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5344 if (r_shadow_shadowmapsampler)
5345 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5346 if (r_shadow_shadowmappcf > 1)
5347 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5348 else if (r_shadow_shadowmappcf)
5349 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5351 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5352 permutation |= SHADERPERMUTATION_REFLECTION;
5353 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5354 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5355 if (rsurface.texture->reflectmasktexture)
5356 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5357 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5358 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5359 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5361 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5363 if (r_glsl_offsetmapping.integer)
5365 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5366 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5367 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5368 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5369 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5371 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5372 if (r_glsl_offsetmapping_reliefmapping.integer)
5373 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5376 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5377 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5378 // ambient model lighting
5379 mode = SHADERMODE_LIGHTDIRECTION;
5380 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5381 permutation |= SHADERPERMUTATION_GLOW;
5382 if (r_refdef.fogenabled)
5383 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5384 if (rsurface.texture->colormapping)
5385 permutation |= SHADERPERMUTATION_COLORMAPPING;
5386 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5388 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5389 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5391 if (r_shadow_shadowmapsampler)
5392 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5393 if (r_shadow_shadowmappcf > 1)
5394 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5395 else if (r_shadow_shadowmappcf)
5396 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5399 permutation |= SHADERPERMUTATION_REFLECTION;
5400 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5401 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5402 if (rsurface.texture->reflectmasktexture)
5403 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5404 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5405 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5406 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5410 if (r_glsl_offsetmapping.integer)
5412 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5413 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5415 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5416 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5418 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5419 if (r_glsl_offsetmapping_reliefmapping.integer)
5420 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5423 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5424 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5426 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5427 permutation |= SHADERPERMUTATION_GLOW;
5428 if (r_refdef.fogenabled)
5429 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5430 if (rsurface.texture->colormapping)
5431 permutation |= SHADERPERMUTATION_COLORMAPPING;
5432 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5434 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5435 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5437 if (r_shadow_shadowmapsampler)
5438 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5439 if (r_shadow_shadowmappcf > 1)
5440 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5441 else if (r_shadow_shadowmappcf)
5442 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5444 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5445 permutation |= SHADERPERMUTATION_REFLECTION;
5446 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5447 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5448 if (rsurface.texture->reflectmasktexture)
5449 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5450 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5452 // deluxemapping (light direction texture)
5453 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5454 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5456 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5457 permutation |= SHADERPERMUTATION_DIFFUSE;
5458 if (specularscale > 0)
5460 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5461 if (r_shadow_glossexact.integer)
5462 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5465 else if (r_glsl_deluxemapping.integer >= 2)
5467 // fake deluxemapping (uniform light direction in tangentspace)
5468 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5469 permutation |= SHADERPERMUTATION_DIFFUSE;
5470 if (specularscale > 0)
5472 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5473 if (r_shadow_glossexact.integer)
5474 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5477 else if (rsurface.uselightmaptexture)
5479 // ordinary lightmapping (q1bsp, q3bsp)
5480 mode = SHADERMODE_LIGHTMAP;
5484 // ordinary vertex coloring (q3bsp)
5485 mode = SHADERMODE_VERTEXCOLOR;
5487 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5488 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5489 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5492 colormod = dummy_colormod;
5493 switch(vid.renderpath)
5495 case RENDERPATH_D3D9:
5497 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);
5498 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5499 R_SetupShader_SetPermutationHLSL(mode, permutation);
5500 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5501 if (mode == SHADERMODE_LIGHTSOURCE)
5503 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5504 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5508 if (mode == SHADERMODE_LIGHTDIRECTION)
5510 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5513 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5514 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5515 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5516 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5517 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5519 if (mode == SHADERMODE_LIGHTSOURCE)
5521 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5522 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5524 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5527 // additive passes are only darkened by fog, not tinted
5528 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5529 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5533 if (mode == SHADERMODE_FLATCOLOR)
5535 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5537 else if (mode == SHADERMODE_LIGHTDIRECTION)
5539 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]);
5540 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5541 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);
5542 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);
5543 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5544 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5545 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5549 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5550 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5551 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);
5552 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);
5553 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5555 // additive passes are only darkened by fog, not tinted
5556 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5557 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5559 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5560 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);
5561 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5562 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5563 hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5564 hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5565 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5566 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5567 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5569 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5570 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5571 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5572 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5573 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5574 if (rsurface.texture->pantstexture)
5575 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5578 if (rsurface.texture->shirttexture)
5579 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5581 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5582 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5583 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5584 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5585 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5586 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5587 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5588 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5590 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5591 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5592 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5593 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5594 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5595 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5596 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5597 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5598 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5599 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5600 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5601 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5602 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5603 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5604 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5605 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5606 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5607 if (rsurfacepass == RSURFPASS_BACKGROUND)
5609 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5610 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5611 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5615 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5617 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5618 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5619 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5620 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5621 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5623 R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5624 if (rsurface.rtlight)
5626 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5627 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5632 case RENDERPATH_D3D10:
5633 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5635 case RENDERPATH_D3D11:
5636 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5638 case RENDERPATH_GL20:
5639 if (gl_mesh_separatearrays.integer)
5641 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);
5642 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5643 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5644 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5645 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5646 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5647 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5648 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5652 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);
5653 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5655 R_SetupShader_SetPermutationGLSL(mode, permutation);
5656 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5657 if (mode == SHADERMODE_LIGHTSOURCE)
5659 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5660 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5661 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5662 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5663 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5664 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);
5666 // additive passes are only darkened by fog, not tinted
5667 if (r_glsl_permutation->loc_FogColor >= 0)
5668 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5669 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5673 if (mode == SHADERMODE_FLATCOLOR)
5675 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5677 else if (mode == SHADERMODE_LIGHTDIRECTION)
5679 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]);
5680 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]);
5681 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);
5682 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);
5683 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);
5684 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]);
5685 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]);
5689 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]);
5690 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]);
5691 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);
5692 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);
5693 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);
5695 // additive passes are only darkened by fog, not tinted
5696 if (r_glsl_permutation->loc_FogColor >= 0)
5698 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5699 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5701 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5703 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);
5704 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]);
5705 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]);
5706 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5707 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5708 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5709 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5710 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5712 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5713 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5714 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5715 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]);
5716 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]);
5718 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5719 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5720 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5721 if (r_glsl_permutation->loc_Color_Pants >= 0)
5723 if (rsurface.texture->pantstexture)
5724 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5726 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5728 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5730 if (rsurface.texture->shirttexture)
5731 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5733 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5735 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]);
5736 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5737 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5738 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5739 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5740 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]);
5741 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5743 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5744 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5745 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5746 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5747 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5748 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5749 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5750 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5751 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5752 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5753 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5754 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5755 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5756 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5757 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5758 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5759 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5760 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5761 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5762 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5763 if (rsurfacepass == RSURFPASS_BACKGROUND)
5765 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5766 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5767 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5771 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5773 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5774 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5775 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5776 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5777 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5779 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5780 if (rsurface.rtlight)
5782 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5783 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5788 case RENDERPATH_CGGL:
5790 if (gl_mesh_separatearrays.integer)
5792 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);
5793 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5794 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5795 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5796 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5797 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5798 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5799 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5803 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);
5804 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5806 R_SetupShader_SetPermutationCG(mode, permutation);
5807 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5808 if (mode == SHADERMODE_LIGHTSOURCE)
5810 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5811 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5815 if (mode == SHADERMODE_LIGHTDIRECTION)
5817 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
5820 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5821 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5822 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5823 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5824 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
5827 if (mode == SHADERMODE_LIGHTSOURCE)
5829 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5830 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5831 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5832 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5833 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
5835 // additive passes are only darkened by fog, not tinted
5836 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5837 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5841 if (mode == SHADERMODE_FLATCOLOR)
5843 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5845 else if (mode == SHADERMODE_LIGHTDIRECTION)
5847 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
5848 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
5849 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
5850 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
5851 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
5852 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
5853 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
5857 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
5858 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
5859 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
5860 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
5861 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
5863 // additive passes are only darkened by fog, not tinted
5864 if (r_cg_permutation->fp_FogColor)
5866 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5867 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5869 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5872 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
5873 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
5874 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
5875 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5876 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5877 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5878 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5879 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5881 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
5882 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
5883 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5884 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5885 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5886 if (r_cg_permutation->fp_Color_Pants)
5888 if (rsurface.texture->pantstexture)
5889 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5891 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5894 if (r_cg_permutation->fp_Color_Shirt)
5896 if (rsurface.texture->shirttexture)
5897 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5899 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5902 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
5903 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5904 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5905 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5906 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5907 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
5908 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5910 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5911 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5912 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5913 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5914 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5915 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5916 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5917 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5918 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5919 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5920 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5921 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5922 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5923 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5924 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
5925 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
5926 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5927 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5928 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5929 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5930 if (rsurfacepass == RSURFPASS_BACKGROUND)
5932 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
5933 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
5934 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
5938 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
5940 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5941 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5942 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5943 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5944 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5946 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5947 if (rsurface.rtlight)
5949 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5950 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5957 case RENDERPATH_GL13:
5958 case RENDERPATH_GL11:
5963 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5965 // select a permutation of the lighting shader appropriate to this
5966 // combination of texture, entity, light source, and fogging, only use the
5967 // minimum features necessary to avoid wasting rendering time in the
5968 // fragment shader on features that are not being used
5969 unsigned int permutation = 0;
5970 unsigned int mode = 0;
5971 const float *lightcolorbase = rtlight->currentcolor;
5972 float ambientscale = rtlight->ambientscale;
5973 float diffusescale = rtlight->diffusescale;
5974 float specularscale = rtlight->specularscale;
5975 // this is the location of the light in view space
5976 vec3_t viewlightorigin;
5977 // this transforms from view space (camera) to light space (cubemap)
5978 matrix4x4_t viewtolight;
5979 matrix4x4_t lighttoview;
5980 float viewtolight16f[16];
5981 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5983 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5984 if (rtlight->currentcubemap != r_texture_whitecube)
5985 permutation |= SHADERPERMUTATION_CUBEFILTER;
5986 if (diffusescale > 0)
5987 permutation |= SHADERPERMUTATION_DIFFUSE;
5988 if (specularscale > 0)
5990 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5991 if (r_shadow_glossexact.integer)
5992 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5994 if (r_shadow_usingshadowmap2d)
5996 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5997 if (r_shadow_shadowmapvsdct)
5998 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6000 if (r_shadow_shadowmapsampler)
6001 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6002 if (r_shadow_shadowmappcf > 1)
6003 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6004 else if (r_shadow_shadowmappcf)
6005 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6007 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6008 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6009 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6010 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6011 switch(vid.renderpath)
6013 case RENDERPATH_D3D9:
6015 R_SetupShader_SetPermutationHLSL(mode, permutation);
6016 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6017 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6018 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6019 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6020 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6021 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6022 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6023 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6024 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6025 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6027 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6028 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6029 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6030 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6031 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6032 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6035 case RENDERPATH_D3D10:
6036 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6038 case RENDERPATH_D3D11:
6039 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6041 case RENDERPATH_GL20:
6042 R_SetupShader_SetPermutationGLSL(mode, permutation);
6043 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6044 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6045 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);
6046 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);
6047 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);
6048 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]);
6049 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]);
6050 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));
6051 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]);
6052 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6054 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6055 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6056 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6057 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6058 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6059 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6061 case RENDERPATH_CGGL:
6063 R_SetupShader_SetPermutationCG(mode, permutation);
6064 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6065 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6066 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
6067 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
6068 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
6069 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
6070 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
6071 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
6072 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
6073 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6075 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6076 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6077 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6078 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6079 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6080 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6083 case RENDERPATH_GL13:
6084 case RENDERPATH_GL11:
6089 #define SKINFRAME_HASH 1024
6093 int loadsequence; // incremented each level change
6094 memexpandablearray_t array;
6095 skinframe_t *hash[SKINFRAME_HASH];
6098 r_skinframe_t r_skinframe;
6100 void R_SkinFrame_PrepareForPurge(void)
6102 r_skinframe.loadsequence++;
6103 // wrap it without hitting zero
6104 if (r_skinframe.loadsequence >= 200)
6105 r_skinframe.loadsequence = 1;
6108 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6112 // mark the skinframe as used for the purging code
6113 skinframe->loadsequence = r_skinframe.loadsequence;
6116 void R_SkinFrame_Purge(void)
6120 for (i = 0;i < SKINFRAME_HASH;i++)
6122 for (s = r_skinframe.hash[i];s;s = s->next)
6124 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6126 if (s->merged == s->base)
6128 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6129 R_PurgeTexture(s->stain );s->stain = NULL;
6130 R_PurgeTexture(s->merged);s->merged = NULL;
6131 R_PurgeTexture(s->base );s->base = NULL;
6132 R_PurgeTexture(s->pants );s->pants = NULL;
6133 R_PurgeTexture(s->shirt );s->shirt = NULL;
6134 R_PurgeTexture(s->nmap );s->nmap = NULL;
6135 R_PurgeTexture(s->gloss );s->gloss = NULL;
6136 R_PurgeTexture(s->glow );s->glow = NULL;
6137 R_PurgeTexture(s->fog );s->fog = NULL;
6138 R_PurgeTexture(s->reflect);s->reflect = NULL;
6139 s->loadsequence = 0;
6145 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6147 char basename[MAX_QPATH];
6149 Image_StripImageExtension(name, basename, sizeof(basename));
6151 if( last == NULL ) {
6153 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6154 item = r_skinframe.hash[hashindex];
6159 // linearly search through the hash bucket
6160 for( ; item ; item = item->next ) {
6161 if( !strcmp( item->basename, basename ) ) {
6168 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6172 char basename[MAX_QPATH];
6174 Image_StripImageExtension(name, basename, sizeof(basename));
6176 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6177 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6178 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6182 rtexture_t *dyntexture;
6183 // check whether its a dynamic texture
6184 dyntexture = CL_GetDynTexture( basename );
6185 if (!add && !dyntexture)
6187 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6188 memset(item, 0, sizeof(*item));
6189 strlcpy(item->basename, basename, sizeof(item->basename));
6190 item->base = dyntexture; // either NULL or dyntexture handle
6191 item->textureflags = textureflags;
6192 item->comparewidth = comparewidth;
6193 item->compareheight = compareheight;
6194 item->comparecrc = comparecrc;
6195 item->next = r_skinframe.hash[hashindex];
6196 r_skinframe.hash[hashindex] = item;
6198 else if( item->base == NULL )
6200 rtexture_t *dyntexture;
6201 // check whether its a dynamic texture
6202 // 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]
6203 dyntexture = CL_GetDynTexture( basename );
6204 item->base = dyntexture; // either NULL or dyntexture handle
6207 R_SkinFrame_MarkUsed(item);
6211 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6213 unsigned long long avgcolor[5], wsum; \
6221 for(pix = 0; pix < cnt; ++pix) \
6224 for(comp = 0; comp < 3; ++comp) \
6226 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6229 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6231 for(comp = 0; comp < 3; ++comp) \
6232 avgcolor[comp] += getpixel * w; \
6235 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6236 avgcolor[4] += getpixel; \
6238 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6240 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6241 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6242 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6243 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6246 extern cvar_t gl_picmip;
6247 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6250 unsigned char *pixels;
6251 unsigned char *bumppixels;
6252 unsigned char *basepixels = NULL;
6253 int basepixels_width = 0;
6254 int basepixels_height = 0;
6255 skinframe_t *skinframe;
6256 rtexture_t *ddsbase = NULL;
6257 qboolean ddshasalpha = false;
6258 float ddsavgcolor[4];
6259 char basename[MAX_QPATH];
6260 int miplevel = R_PicmipForFlags(textureflags);
6261 int savemiplevel = miplevel;
6264 if (cls.state == ca_dedicated)
6267 // return an existing skinframe if already loaded
6268 // if loading of the first image fails, don't make a new skinframe as it
6269 // would cause all future lookups of this to be missing
6270 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6271 if (skinframe && skinframe->base)
6274 Image_StripImageExtension(name, basename, sizeof(basename));
6276 // check for DDS texture file first
6277 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6279 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6280 if (basepixels == NULL)
6284 // FIXME handle miplevel
6286 if (developer_loading.integer)
6287 Con_Printf("loading skin \"%s\"\n", name);
6289 // we've got some pixels to store, so really allocate this new texture now
6291 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6292 skinframe->stain = NULL;
6293 skinframe->merged = NULL;
6294 skinframe->base = NULL;
6295 skinframe->pants = NULL;
6296 skinframe->shirt = NULL;
6297 skinframe->nmap = NULL;
6298 skinframe->gloss = NULL;
6299 skinframe->glow = NULL;
6300 skinframe->fog = NULL;
6301 skinframe->reflect = NULL;
6302 skinframe->hasalpha = false;
6306 skinframe->base = ddsbase;
6307 skinframe->hasalpha = ddshasalpha;
6308 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6309 if (r_loadfog && skinframe->hasalpha)
6310 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6311 //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]);
6315 basepixels_width = image_width;
6316 basepixels_height = image_height;
6317 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);
6318 if (textureflags & TEXF_ALPHA)
6320 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6322 if (basepixels[j] < 255)
6324 skinframe->hasalpha = true;
6328 if (r_loadfog && skinframe->hasalpha)
6330 // has transparent pixels
6331 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6332 for (j = 0;j < image_width * image_height * 4;j += 4)
6337 pixels[j+3] = basepixels[j+3];
6339 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);
6343 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6344 //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]);
6345 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6346 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6347 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6348 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6353 mymiplevel = savemiplevel;
6354 if (r_loadnormalmap)
6355 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);
6356 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6358 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6359 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6360 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6361 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6364 // _norm is the name used by tenebrae and has been adopted as standard
6365 if (r_loadnormalmap && skinframe->nmap == NULL)
6367 mymiplevel = savemiplevel;
6368 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6370 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);
6374 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6376 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6377 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6378 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);
6380 Mem_Free(bumppixels);
6382 else if (r_shadow_bumpscale_basetexture.value > 0)
6384 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6385 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6386 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);
6389 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6390 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6393 // _luma is supported only for tenebrae compatibility
6394 // _glow is the preferred name
6395 mymiplevel = savemiplevel;
6396 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))))
6398 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);
6399 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6400 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6401 Mem_Free(pixels);pixels = NULL;
6404 mymiplevel = savemiplevel;
6405 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6407 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);
6408 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6409 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6414 mymiplevel = savemiplevel;
6415 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6417 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);
6418 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6419 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6424 mymiplevel = savemiplevel;
6425 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6427 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);
6428 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6429 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6434 mymiplevel = savemiplevel;
6435 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6437 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);
6438 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6439 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6445 Mem_Free(basepixels);
6450 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6451 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6454 unsigned char *temp1, *temp2;
6455 skinframe_t *skinframe;
6457 if (cls.state == ca_dedicated)
6460 // if already loaded just return it, otherwise make a new skinframe
6461 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6462 if (skinframe && skinframe->base)
6465 skinframe->stain = NULL;
6466 skinframe->merged = NULL;
6467 skinframe->base = NULL;
6468 skinframe->pants = NULL;
6469 skinframe->shirt = NULL;
6470 skinframe->nmap = NULL;
6471 skinframe->gloss = NULL;
6472 skinframe->glow = NULL;
6473 skinframe->fog = NULL;
6474 skinframe->reflect = NULL;
6475 skinframe->hasalpha = false;
6477 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6481 if (developer_loading.integer)
6482 Con_Printf("loading 32bit skin \"%s\"\n", name);
6484 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6486 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6487 temp2 = temp1 + width * height * 4;
6488 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6489 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);
6492 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6493 if (textureflags & TEXF_ALPHA)
6495 for (i = 3;i < width * height * 4;i += 4)
6497 if (skindata[i] < 255)
6499 skinframe->hasalpha = true;
6503 if (r_loadfog && skinframe->hasalpha)
6505 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6506 memcpy(fogpixels, skindata, width * height * 4);
6507 for (i = 0;i < width * height * 4;i += 4)
6508 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6509 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6510 Mem_Free(fogpixels);
6514 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6515 //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]);
6520 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6524 skinframe_t *skinframe;
6526 if (cls.state == ca_dedicated)
6529 // if already loaded just return it, otherwise make a new skinframe
6530 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6531 if (skinframe && skinframe->base)
6534 skinframe->stain = NULL;
6535 skinframe->merged = NULL;
6536 skinframe->base = NULL;
6537 skinframe->pants = NULL;
6538 skinframe->shirt = NULL;
6539 skinframe->nmap = NULL;
6540 skinframe->gloss = NULL;
6541 skinframe->glow = NULL;
6542 skinframe->fog = NULL;
6543 skinframe->reflect = NULL;
6544 skinframe->hasalpha = false;
6546 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6550 if (developer_loading.integer)
6551 Con_Printf("loading quake skin \"%s\"\n", name);
6553 // 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)
6554 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6555 memcpy(skinframe->qpixels, skindata, width*height);
6556 skinframe->qwidth = width;
6557 skinframe->qheight = height;
6560 for (i = 0;i < width * height;i++)
6561 featuresmask |= palette_featureflags[skindata[i]];
6563 skinframe->hasalpha = false;
6564 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6565 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6566 skinframe->qgeneratemerged = true;
6567 skinframe->qgeneratebase = skinframe->qhascolormapping;
6568 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6570 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6571 //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]);
6576 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6580 unsigned char *skindata;
6582 if (!skinframe->qpixels)
6585 if (!skinframe->qhascolormapping)
6586 colormapped = false;
6590 if (!skinframe->qgeneratebase)
6595 if (!skinframe->qgeneratemerged)
6599 width = skinframe->qwidth;
6600 height = skinframe->qheight;
6601 skindata = skinframe->qpixels;
6603 if (skinframe->qgeneratenmap)
6605 unsigned char *temp1, *temp2;
6606 skinframe->qgeneratenmap = false;
6607 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6608 temp2 = temp1 + width * height * 4;
6609 // use either a custom palette or the quake palette
6610 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6611 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6612 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);
6616 if (skinframe->qgenerateglow)
6618 skinframe->qgenerateglow = false;
6619 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6624 skinframe->qgeneratebase = false;
6625 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);
6626 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6627 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6631 skinframe->qgeneratemerged = false;
6632 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);
6635 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6637 Mem_Free(skinframe->qpixels);
6638 skinframe->qpixels = NULL;
6642 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)
6645 skinframe_t *skinframe;
6647 if (cls.state == ca_dedicated)
6650 // if already loaded just return it, otherwise make a new skinframe
6651 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6652 if (skinframe && skinframe->base)
6655 skinframe->stain = NULL;
6656 skinframe->merged = NULL;
6657 skinframe->base = NULL;
6658 skinframe->pants = NULL;
6659 skinframe->shirt = NULL;
6660 skinframe->nmap = NULL;
6661 skinframe->gloss = NULL;
6662 skinframe->glow = NULL;
6663 skinframe->fog = NULL;
6664 skinframe->reflect = NULL;
6665 skinframe->hasalpha = false;
6667 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6671 if (developer_loading.integer)
6672 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6674 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6675 if (textureflags & TEXF_ALPHA)
6677 for (i = 0;i < width * height;i++)
6679 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6681 skinframe->hasalpha = true;
6685 if (r_loadfog && skinframe->hasalpha)
6686 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6689 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6690 //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]);
6695 skinframe_t *R_SkinFrame_LoadMissing(void)
6697 skinframe_t *skinframe;
6699 if (cls.state == ca_dedicated)
6702 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6703 skinframe->stain = NULL;
6704 skinframe->merged = NULL;
6705 skinframe->base = NULL;
6706 skinframe->pants = NULL;
6707 skinframe->shirt = NULL;
6708 skinframe->nmap = NULL;
6709 skinframe->gloss = NULL;
6710 skinframe->glow = NULL;
6711 skinframe->fog = NULL;
6712 skinframe->reflect = NULL;
6713 skinframe->hasalpha = false;
6715 skinframe->avgcolor[0] = rand() / RAND_MAX;
6716 skinframe->avgcolor[1] = rand() / RAND_MAX;
6717 skinframe->avgcolor[2] = rand() / RAND_MAX;
6718 skinframe->avgcolor[3] = 1;
6723 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6724 typedef struct suffixinfo_s
6727 qboolean flipx, flipy, flipdiagonal;
6730 static suffixinfo_t suffix[3][6] =
6733 {"px", false, false, false},
6734 {"nx", false, false, false},
6735 {"py", false, false, false},
6736 {"ny", false, false, false},
6737 {"pz", false, false, false},
6738 {"nz", false, false, false}
6741 {"posx", false, false, false},
6742 {"negx", false, false, false},
6743 {"posy", false, false, false},
6744 {"negy", false, false, false},
6745 {"posz", false, false, false},
6746 {"negz", false, false, false}
6749 {"rt", true, false, true},
6750 {"lf", false, true, true},
6751 {"ft", true, true, false},
6752 {"bk", false, false, false},
6753 {"up", true, false, true},
6754 {"dn", true, false, true}
6758 static int componentorder[4] = {0, 1, 2, 3};
6760 rtexture_t *R_LoadCubemap(const char *basename)
6762 int i, j, cubemapsize;
6763 unsigned char *cubemappixels, *image_buffer;
6764 rtexture_t *cubemaptexture;
6766 // must start 0 so the first loadimagepixels has no requested width/height
6768 cubemappixels = NULL;
6769 cubemaptexture = NULL;
6770 // keep trying different suffix groups (posx, px, rt) until one loads
6771 for (j = 0;j < 3 && !cubemappixels;j++)
6773 // load the 6 images in the suffix group
6774 for (i = 0;i < 6;i++)
6776 // generate an image name based on the base and and suffix
6777 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6779 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6781 // an image loaded, make sure width and height are equal
6782 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6784 // if this is the first image to load successfully, allocate the cubemap memory
6785 if (!cubemappixels && image_width >= 1)
6787 cubemapsize = image_width;
6788 // note this clears to black, so unavailable sides are black
6789 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6791 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6793 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);
6796 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6798 Mem_Free(image_buffer);
6802 // if a cubemap loaded, upload it
6805 if (developer_loading.integer)
6806 Con_Printf("loading cubemap \"%s\"\n", basename);
6808 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6809 Mem_Free(cubemappixels);
6813 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6814 if (developer_loading.integer)
6816 Con_Printf("(tried tried images ");
6817 for (j = 0;j < 3;j++)
6818 for (i = 0;i < 6;i++)
6819 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6820 Con_Print(" and was unable to find any of them).\n");
6823 return cubemaptexture;
6826 rtexture_t *R_GetCubemap(const char *basename)
6829 for (i = 0;i < r_texture_numcubemaps;i++)
6830 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6831 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6832 if (i >= MAX_CUBEMAPS)
6833 return r_texture_whitecube;
6834 r_texture_numcubemaps++;
6835 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6836 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6837 return r_texture_cubemaps[i].texture;
6840 void R_FreeCubemaps(void)
6843 for (i = 0;i < r_texture_numcubemaps;i++)
6845 if (developer_loading.integer)
6846 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6847 if (r_texture_cubemaps[i].texture)
6848 R_FreeTexture(r_texture_cubemaps[i].texture);
6850 r_texture_numcubemaps = 0;
6853 void R_Main_FreeViewCache(void)
6855 if (r_refdef.viewcache.entityvisible)
6856 Mem_Free(r_refdef.viewcache.entityvisible);
6857 if (r_refdef.viewcache.world_pvsbits)
6858 Mem_Free(r_refdef.viewcache.world_pvsbits);
6859 if (r_refdef.viewcache.world_leafvisible)
6860 Mem_Free(r_refdef.viewcache.world_leafvisible);
6861 if (r_refdef.viewcache.world_surfacevisible)
6862 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6863 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6866 void R_Main_ResizeViewCache(void)
6868 int numentities = r_refdef.scene.numentities;
6869 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6870 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6871 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6872 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6873 if (r_refdef.viewcache.maxentities < numentities)
6875 r_refdef.viewcache.maxentities = numentities;
6876 if (r_refdef.viewcache.entityvisible)
6877 Mem_Free(r_refdef.viewcache.entityvisible);
6878 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6880 if (r_refdef.viewcache.world_numclusters != numclusters)
6882 r_refdef.viewcache.world_numclusters = numclusters;
6883 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6884 if (r_refdef.viewcache.world_pvsbits)
6885 Mem_Free(r_refdef.viewcache.world_pvsbits);
6886 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6888 if (r_refdef.viewcache.world_numleafs != numleafs)
6890 r_refdef.viewcache.world_numleafs = numleafs;
6891 if (r_refdef.viewcache.world_leafvisible)
6892 Mem_Free(r_refdef.viewcache.world_leafvisible);
6893 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6895 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6897 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6898 if (r_refdef.viewcache.world_surfacevisible)
6899 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6900 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6904 extern rtexture_t *loadingscreentexture;
6905 void gl_main_start(void)
6907 loadingscreentexture = NULL;
6908 r_texture_blanknormalmap = NULL;
6909 r_texture_white = NULL;
6910 r_texture_grey128 = NULL;
6911 r_texture_black = NULL;
6912 r_texture_whitecube = NULL;
6913 r_texture_normalizationcube = NULL;
6914 r_texture_fogattenuation = NULL;
6915 r_texture_fogheighttexture = NULL;
6916 r_texture_gammaramps = NULL;
6917 r_texture_numcubemaps = 0;
6919 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6920 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6922 switch(vid.renderpath)
6924 case RENDERPATH_GL20:
6925 case RENDERPATH_CGGL:
6926 case RENDERPATH_D3D9:
6927 case RENDERPATH_D3D10:
6928 case RENDERPATH_D3D11:
6929 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6930 Cvar_SetValueQuick(&gl_combine, 1);
6931 Cvar_SetValueQuick(&r_glsl, 1);
6932 r_loadnormalmap = true;
6936 case RENDERPATH_GL13:
6937 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6938 Cvar_SetValueQuick(&gl_combine, 1);
6939 Cvar_SetValueQuick(&r_glsl, 0);
6940 r_loadnormalmap = false;
6941 r_loadgloss = false;
6944 case RENDERPATH_GL11:
6945 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6946 Cvar_SetValueQuick(&gl_combine, 0);
6947 Cvar_SetValueQuick(&r_glsl, 0);
6948 r_loadnormalmap = false;
6949 r_loadgloss = false;
6955 R_FrameData_Reset();
6959 memset(r_queries, 0, sizeof(r_queries));
6961 r_qwskincache = NULL;
6962 r_qwskincache_size = 0;
6964 // set up r_skinframe loading system for textures
6965 memset(&r_skinframe, 0, sizeof(r_skinframe));
6966 r_skinframe.loadsequence = 1;
6967 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6969 r_main_texturepool = R_AllocTexturePool();
6970 R_BuildBlankTextures();
6972 if (vid.support.arb_texture_cube_map)
6975 R_BuildNormalizationCube();
6977 r_texture_fogattenuation = NULL;
6978 r_texture_fogheighttexture = NULL;
6979 r_texture_gammaramps = NULL;
6980 //r_texture_fogintensity = NULL;
6981 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6982 memset(&r_waterstate, 0, sizeof(r_waterstate));
6983 r_glsl_permutation = NULL;
6984 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6985 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6986 glslshaderstring = NULL;
6988 r_cg_permutation = NULL;
6989 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6990 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6991 cgshaderstring = NULL;
6994 r_hlsl_permutation = NULL;
6995 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6996 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6997 hlslshaderstring = NULL;
6999 memset(&r_svbsp, 0, sizeof (r_svbsp));
7001 r_refdef.fogmasktable_density = 0;
7004 void gl_main_shutdown(void)
7007 R_FrameData_Reset();
7009 R_Main_FreeViewCache();
7011 switch(vid.renderpath)
7013 case RENDERPATH_GL11:
7014 case RENDERPATH_GL13:
7015 case RENDERPATH_GL20:
7016 case RENDERPATH_CGGL:
7018 qglDeleteQueriesARB(r_maxqueries, r_queries);
7020 case RENDERPATH_D3D9:
7021 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7023 case RENDERPATH_D3D10:
7024 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7026 case RENDERPATH_D3D11:
7027 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7033 memset(r_queries, 0, sizeof(r_queries));
7035 r_qwskincache = NULL;
7036 r_qwskincache_size = 0;
7038 // clear out the r_skinframe state
7039 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7040 memset(&r_skinframe, 0, sizeof(r_skinframe));
7043 Mem_Free(r_svbsp.nodes);
7044 memset(&r_svbsp, 0, sizeof (r_svbsp));
7045 R_FreeTexturePool(&r_main_texturepool);
7046 loadingscreentexture = NULL;
7047 r_texture_blanknormalmap = NULL;
7048 r_texture_white = NULL;
7049 r_texture_grey128 = NULL;
7050 r_texture_black = NULL;
7051 r_texture_whitecube = NULL;
7052 r_texture_normalizationcube = NULL;
7053 r_texture_fogattenuation = NULL;
7054 r_texture_fogheighttexture = NULL;
7055 r_texture_gammaramps = NULL;
7056 r_texture_numcubemaps = 0;
7057 //r_texture_fogintensity = NULL;
7058 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7059 memset(&r_waterstate, 0, sizeof(r_waterstate));
7063 extern void CL_ParseEntityLump(char *entitystring);
7064 void gl_main_newmap(void)
7066 // FIXME: move this code to client
7067 char *entities, entname[MAX_QPATH];
7069 Mem_Free(r_qwskincache);
7070 r_qwskincache = NULL;
7071 r_qwskincache_size = 0;
7074 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7075 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7077 CL_ParseEntityLump(entities);
7081 if (cl.worldmodel->brush.entities)
7082 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7084 R_Main_FreeViewCache();
7086 R_FrameData_Reset();
7089 void GL_Main_Init(void)
7091 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7093 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7094 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7095 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7096 if (gamemode == GAME_NEHAHRA)
7098 Cvar_RegisterVariable (&gl_fogenable);
7099 Cvar_RegisterVariable (&gl_fogdensity);
7100 Cvar_RegisterVariable (&gl_fogred);
7101 Cvar_RegisterVariable (&gl_foggreen);
7102 Cvar_RegisterVariable (&gl_fogblue);
7103 Cvar_RegisterVariable (&gl_fogstart);
7104 Cvar_RegisterVariable (&gl_fogend);
7105 Cvar_RegisterVariable (&gl_skyclip);
7107 Cvar_RegisterVariable(&r_motionblur);
7108 Cvar_RegisterVariable(&r_motionblur_maxblur);
7109 Cvar_RegisterVariable(&r_motionblur_bmin);
7110 Cvar_RegisterVariable(&r_motionblur_vmin);
7111 Cvar_RegisterVariable(&r_motionblur_vmax);
7112 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7113 Cvar_RegisterVariable(&r_motionblur_randomize);
7114 Cvar_RegisterVariable(&r_damageblur);
7115 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7116 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7117 Cvar_RegisterVariable(&r_equalize_entities_by);
7118 Cvar_RegisterVariable(&r_equalize_entities_to);
7119 Cvar_RegisterVariable(&r_depthfirst);
7120 Cvar_RegisterVariable(&r_useinfinitefarclip);
7121 Cvar_RegisterVariable(&r_farclip_base);
7122 Cvar_RegisterVariable(&r_farclip_world);
7123 Cvar_RegisterVariable(&r_nearclip);
7124 Cvar_RegisterVariable(&r_showbboxes);
7125 Cvar_RegisterVariable(&r_showsurfaces);
7126 Cvar_RegisterVariable(&r_showtris);
7127 Cvar_RegisterVariable(&r_shownormals);
7128 Cvar_RegisterVariable(&r_showlighting);
7129 Cvar_RegisterVariable(&r_showshadowvolumes);
7130 Cvar_RegisterVariable(&r_showcollisionbrushes);
7131 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7132 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7133 Cvar_RegisterVariable(&r_showdisabledepthtest);
7134 Cvar_RegisterVariable(&r_drawportals);
7135 Cvar_RegisterVariable(&r_drawentities);
7136 Cvar_RegisterVariable(&r_draw2d);
7137 Cvar_RegisterVariable(&r_drawworld);
7138 Cvar_RegisterVariable(&r_cullentities_trace);
7139 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7140 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7141 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7142 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7143 Cvar_RegisterVariable(&r_drawviewmodel);
7144 Cvar_RegisterVariable(&r_drawexteriormodel);
7145 Cvar_RegisterVariable(&r_speeds);
7146 Cvar_RegisterVariable(&r_fullbrights);
7147 Cvar_RegisterVariable(&r_wateralpha);
7148 Cvar_RegisterVariable(&r_dynamic);
7149 Cvar_RegisterVariable(&r_fullbright);
7150 Cvar_RegisterVariable(&r_shadows);
7151 Cvar_RegisterVariable(&r_shadows_darken);
7152 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7153 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7154 Cvar_RegisterVariable(&r_shadows_throwdistance);
7155 Cvar_RegisterVariable(&r_shadows_throwdirection);
7156 Cvar_RegisterVariable(&r_shadows_focus);
7157 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7158 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7159 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7160 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7161 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7162 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7163 Cvar_RegisterVariable(&r_fog_exp2);
7164 Cvar_RegisterVariable(&r_drawfog);
7165 Cvar_RegisterVariable(&r_transparentdepthmasking);
7166 Cvar_RegisterVariable(&r_texture_dds_load);
7167 Cvar_RegisterVariable(&r_texture_dds_save);
7168 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7169 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7170 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7171 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7172 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7173 Cvar_RegisterVariable(&r_textureunits);
7174 Cvar_RegisterVariable(&gl_combine);
7175 Cvar_RegisterVariable(&r_glsl);
7176 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7177 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7178 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7179 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7180 Cvar_RegisterVariable(&r_glsl_postprocess);
7181 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7182 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7183 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7184 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7185 Cvar_RegisterVariable(&r_water);
7186 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7187 Cvar_RegisterVariable(&r_water_clippingplanebias);
7188 Cvar_RegisterVariable(&r_water_refractdistort);
7189 Cvar_RegisterVariable(&r_water_reflectdistort);
7190 Cvar_RegisterVariable(&r_lerpsprites);
7191 Cvar_RegisterVariable(&r_lerpmodels);
7192 Cvar_RegisterVariable(&r_lerplightstyles);
7193 Cvar_RegisterVariable(&r_waterscroll);
7194 Cvar_RegisterVariable(&r_bloom);
7195 Cvar_RegisterVariable(&r_bloom_colorscale);
7196 Cvar_RegisterVariable(&r_bloom_brighten);
7197 Cvar_RegisterVariable(&r_bloom_blur);
7198 Cvar_RegisterVariable(&r_bloom_resolution);
7199 Cvar_RegisterVariable(&r_bloom_colorexponent);
7200 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7201 Cvar_RegisterVariable(&r_hdr);
7202 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7203 Cvar_RegisterVariable(&r_hdr_glowintensity);
7204 Cvar_RegisterVariable(&r_hdr_range);
7205 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7206 Cvar_RegisterVariable(&developer_texturelogging);
7207 Cvar_RegisterVariable(&gl_lightmaps);
7208 Cvar_RegisterVariable(&r_test);
7209 Cvar_RegisterVariable(&r_glsl_saturation);
7210 Cvar_RegisterVariable(&r_framedatasize);
7211 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7212 Cvar_SetValue("r_fullbrights", 0);
7213 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7215 Cvar_RegisterVariable(&r_track_sprites);
7216 Cvar_RegisterVariable(&r_track_sprites_flags);
7217 Cvar_RegisterVariable(&r_track_sprites_scalew);
7218 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7219 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7220 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7223 extern void R_Textures_Init(void);
7224 extern void GL_Draw_Init(void);
7225 extern void GL_Main_Init(void);
7226 extern void R_Shadow_Init(void);
7227 extern void R_Sky_Init(void);
7228 extern void GL_Surf_Init(void);
7229 extern void R_Particles_Init(void);
7230 extern void R_Explosion_Init(void);
7231 extern void gl_backend_init(void);
7232 extern void Sbar_Init(void);
7233 extern void R_LightningBeams_Init(void);
7234 extern void Mod_RenderInit(void);
7235 extern void Font_Init(void);
7237 void Render_Init(void)
7250 R_LightningBeams_Init();
7259 extern char *ENGINE_EXTENSIONS;
7262 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7263 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7264 gl_version = (const char *)qglGetString(GL_VERSION);
7265 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7269 if (!gl_platformextensions)
7270 gl_platformextensions = "";
7272 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7273 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7274 Con_Printf("GL_VERSION: %s\n", gl_version);
7275 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7276 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7278 VID_CheckExtensions();
7280 // LordHavoc: report supported extensions
7281 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7283 // clear to black (loading plaque will be seen over this)
7284 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7287 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7291 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7293 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7296 p = r_refdef.view.frustum + i;
7301 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7305 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7309 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7313 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7317 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7321 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7325 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7329 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7337 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7341 for (i = 0;i < numplanes;i++)
7348 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7352 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7356 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7360 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7364 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7368 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7372 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7376 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7384 //==================================================================================
7386 // LordHavoc: this stores temporary data used within the same frame
7388 qboolean r_framedata_failed;
7389 static size_t r_framedata_size;
7390 static size_t r_framedata_current;
7391 static void *r_framedata_base;
7393 void R_FrameData_Reset(void)
7395 if (r_framedata_base)
7396 Mem_Free(r_framedata_base);
7397 r_framedata_base = NULL;
7398 r_framedata_size = 0;
7399 r_framedata_current = 0;
7400 r_framedata_failed = false;
7403 void R_FrameData_NewFrame(void)
7406 if (r_framedata_failed)
7407 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7408 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7409 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7410 if (r_framedata_size != wantedsize)
7412 r_framedata_size = wantedsize;
7413 if (r_framedata_base)
7414 Mem_Free(r_framedata_base);
7415 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7417 r_framedata_current = 0;
7418 r_framedata_failed = false;
7421 void *R_FrameData_Alloc(size_t size)
7425 // align to 16 byte boundary
7426 size = (size + 15) & ~15;
7427 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7428 r_framedata_current += size;
7431 if (r_framedata_current > r_framedata_size)
7432 r_framedata_failed = true;
7434 // return NULL on everything after a failure
7435 if (r_framedata_failed)
7441 void *R_FrameData_Store(size_t size, void *data)
7443 void *d = R_FrameData_Alloc(size);
7445 memcpy(d, data, size);
7449 //==================================================================================
7451 // LordHavoc: animcache originally written by Echon, rewritten since then
7454 * Animation cache prevents re-generating mesh data for an animated model
7455 * multiple times in one frame for lighting, shadowing, reflections, etc.
7458 void R_AnimCache_Free(void)
7462 void R_AnimCache_ClearCache(void)
7465 entity_render_t *ent;
7467 for (i = 0;i < r_refdef.scene.numentities;i++)
7469 ent = r_refdef.scene.entities[i];
7470 ent->animcache_vertex3f = NULL;
7471 ent->animcache_normal3f = NULL;
7472 ent->animcache_svector3f = NULL;
7473 ent->animcache_tvector3f = NULL;
7474 ent->animcache_vertexposition = NULL;
7475 ent->animcache_vertexmesh = NULL;
7476 ent->animcache_vertexpositionbuffer = NULL;
7477 ent->animcache_vertexmeshbuffer = NULL;
7481 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7485 // identical memory layout, so no need to allocate...
7486 // this also provides the vertexposition structure to everything, e.g.
7487 // depth masked rendering currently uses it even if having separate
7489 // NOTE: get rid of this optimization if changing it to e.g. 4f
7490 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7493 // get rid of following uses of VERTEXPOSITION, change to the array:
7494 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7495 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7496 // R_DrawTextureSurfaceList_DepthOnly
7497 // R_Q1BSP_DrawShadowMap
7499 switch(vid.renderpath)
7501 case RENDERPATH_GL20:
7502 case RENDERPATH_CGGL:
7503 // need the meshbuffers if !gl_mesh_separatearrays.integer
7504 if (gl_mesh_separatearrays.integer)
7507 case RENDERPATH_D3D9:
7508 case RENDERPATH_D3D10:
7509 case RENDERPATH_D3D11:
7510 // always need the meshbuffers
7512 case RENDERPATH_GL13:
7513 case RENDERPATH_GL11:
7514 // never need the meshbuffers
7518 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7519 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7521 if (!ent->animcache_vertexposition)
7522 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7524 if (ent->animcache_vertexposition)
7527 for (i = 0;i < numvertices;i++)
7528 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7530 // TODO: upload vertex buffer?
7532 if (ent->animcache_vertexmesh)
7534 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7535 for (i = 0;i < numvertices;i++)
7536 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7537 if (ent->animcache_svector3f)
7538 for (i = 0;i < numvertices;i++)
7539 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7540 if (ent->animcache_tvector3f)
7541 for (i = 0;i < numvertices;i++)
7542 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7543 if (ent->animcache_normal3f)
7544 for (i = 0;i < numvertices;i++)
7545 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7546 // TODO: upload vertex buffer?
7550 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7552 dp_model_t *model = ent->model;
7554 // see if it's already cached this frame
7555 if (ent->animcache_vertex3f)
7557 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7558 if (wantnormals || wanttangents)
7560 if (ent->animcache_normal3f)
7561 wantnormals = false;
7562 if (ent->animcache_svector3f)
7563 wanttangents = false;
7564 if (wantnormals || wanttangents)
7566 numvertices = model->surfmesh.num_vertices;
7568 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7571 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7572 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7574 if (!r_framedata_failed)
7576 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7577 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7584 // see if this ent is worth caching
7585 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7587 // get some memory for this entity and generate mesh data
7588 numvertices = model->surfmesh.num_vertices;
7589 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7591 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7594 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7595 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7597 if (!r_framedata_failed)
7599 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7600 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7603 return !r_framedata_failed;
7606 void R_AnimCache_CacheVisibleEntities(void)
7609 qboolean wantnormals = true;
7610 qboolean wanttangents = !r_showsurfaces.integer;
7612 switch(vid.renderpath)
7614 case RENDERPATH_GL20:
7615 case RENDERPATH_CGGL:
7616 case RENDERPATH_D3D9:
7617 case RENDERPATH_D3D10:
7618 case RENDERPATH_D3D11:
7620 case RENDERPATH_GL13:
7621 case RENDERPATH_GL11:
7622 wanttangents = false;
7626 if (r_shownormals.integer)
7627 wanttangents = wantnormals = true;
7629 // TODO: thread this
7630 // NOTE: R_PrepareRTLights() also caches entities
7632 for (i = 0;i < r_refdef.scene.numentities;i++)
7633 if (r_refdef.viewcache.entityvisible[i])
7634 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7637 //==================================================================================
7639 static void R_View_UpdateEntityLighting (void)
7642 entity_render_t *ent;
7643 vec3_t tempdiffusenormal, avg;
7644 vec_t f, fa, fd, fdd;
7645 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7647 for (i = 0;i < r_refdef.scene.numentities;i++)
7649 ent = r_refdef.scene.entities[i];
7651 // skip unseen models
7652 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7656 if (ent->model && ent->model->brush.num_leafs)
7658 // TODO: use modellight for r_ambient settings on world?
7659 VectorSet(ent->modellight_ambient, 0, 0, 0);
7660 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7661 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7665 // fetch the lighting from the worldmodel data
7666 VectorClear(ent->modellight_ambient);
7667 VectorClear(ent->modellight_diffuse);
7668 VectorClear(tempdiffusenormal);
7669 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7672 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7673 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7674 if(ent->flags & RENDER_EQUALIZE)
7676 // first fix up ambient lighting...
7677 if(r_equalize_entities_minambient.value > 0)
7679 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7682 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7683 if(fa < r_equalize_entities_minambient.value * fd)
7686 // fa'/fd' = minambient
7687 // fa'+0.25*fd' = fa+0.25*fd
7689 // fa' = fd' * minambient
7690 // fd'*(0.25+minambient) = fa+0.25*fd
7692 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7693 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7695 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7696 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
7697 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7698 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7703 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7705 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7706 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7709 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7710 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7711 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7717 VectorSet(ent->modellight_ambient, 1, 1, 1);
7719 // move the light direction into modelspace coordinates for lighting code
7720 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7721 if(VectorLength2(ent->modellight_lightdir) == 0)
7722 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7723 VectorNormalize(ent->modellight_lightdir);
7727 #define MAX_LINEOFSIGHTTRACES 64
7729 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7732 vec3_t boxmins, boxmaxs;
7735 dp_model_t *model = r_refdef.scene.worldmodel;
7737 if (!model || !model->brush.TraceLineOfSight)
7740 // expand the box a little
7741 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7742 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7743 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7744 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7745 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7746 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7748 // return true if eye is inside enlarged box
7749 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7753 VectorCopy(eye, start);
7754 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7755 if (model->brush.TraceLineOfSight(model, start, end))
7758 // try various random positions
7759 for (i = 0;i < numsamples;i++)
7761 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7762 if (model->brush.TraceLineOfSight(model, start, end))
7770 static void R_View_UpdateEntityVisible (void)
7775 entity_render_t *ent;
7777 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7778 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7779 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7780 : RENDER_EXTERIORMODEL;
7781 if (!r_drawviewmodel.integer)
7782 renderimask |= RENDER_VIEWMODEL;
7783 if (!r_drawexteriormodel.integer)
7784 renderimask |= RENDER_EXTERIORMODEL;
7785 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7787 // worldmodel can check visibility
7788 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7789 for (i = 0;i < r_refdef.scene.numentities;i++)
7791 ent = r_refdef.scene.entities[i];
7792 if (!(ent->flags & renderimask))
7793 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)))
7794 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))
7795 r_refdef.viewcache.entityvisible[i] = true;
7797 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7798 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7800 for (i = 0;i < r_refdef.scene.numentities;i++)
7802 ent = r_refdef.scene.entities[i];
7803 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7805 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7807 continue; // temp entities do pvs only
7808 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7809 ent->last_trace_visibility = realtime;
7810 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7811 r_refdef.viewcache.entityvisible[i] = 0;
7818 // no worldmodel or it can't check visibility
7819 for (i = 0;i < r_refdef.scene.numentities;i++)
7821 ent = r_refdef.scene.entities[i];
7822 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));
7827 /// only used if skyrendermasked, and normally returns false
7828 int R_DrawBrushModelsSky (void)
7831 entity_render_t *ent;
7834 for (i = 0;i < r_refdef.scene.numentities;i++)
7836 if (!r_refdef.viewcache.entityvisible[i])
7838 ent = r_refdef.scene.entities[i];
7839 if (!ent->model || !ent->model->DrawSky)
7841 ent->model->DrawSky(ent);
7847 static void R_DrawNoModel(entity_render_t *ent);
7848 static void R_DrawModels(void)
7851 entity_render_t *ent;
7853 for (i = 0;i < r_refdef.scene.numentities;i++)
7855 if (!r_refdef.viewcache.entityvisible[i])
7857 ent = r_refdef.scene.entities[i];
7858 r_refdef.stats.entities++;
7859 if (ent->model && ent->model->Draw != NULL)
7860 ent->model->Draw(ent);
7866 static void R_DrawModelsDepth(void)
7869 entity_render_t *ent;
7871 for (i = 0;i < r_refdef.scene.numentities;i++)
7873 if (!r_refdef.viewcache.entityvisible[i])
7875 ent = r_refdef.scene.entities[i];
7876 if (ent->model && ent->model->DrawDepth != NULL)
7877 ent->model->DrawDepth(ent);
7881 static void R_DrawModelsDebug(void)
7884 entity_render_t *ent;
7886 for (i = 0;i < r_refdef.scene.numentities;i++)
7888 if (!r_refdef.viewcache.entityvisible[i])
7890 ent = r_refdef.scene.entities[i];
7891 if (ent->model && ent->model->DrawDebug != NULL)
7892 ent->model->DrawDebug(ent);
7896 static void R_DrawModelsAddWaterPlanes(void)
7899 entity_render_t *ent;
7901 for (i = 0;i < r_refdef.scene.numentities;i++)
7903 if (!r_refdef.viewcache.entityvisible[i])
7905 ent = r_refdef.scene.entities[i];
7906 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7907 ent->model->DrawAddWaterPlanes(ent);
7911 static void R_View_SetFrustum(void)
7914 double slopex, slopey;
7915 vec3_t forward, left, up, origin;
7917 // we can't trust r_refdef.view.forward and friends in reflected scenes
7918 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7921 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7922 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7923 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7924 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7925 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7926 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7927 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7928 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7929 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7930 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7931 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7932 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7936 zNear = r_refdef.nearclip;
7937 nudge = 1.0 - 1.0 / (1<<23);
7938 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7939 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7940 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7941 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7942 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7943 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7944 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7945 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7951 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7952 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7953 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7954 r_refdef.view.frustum[0].dist = m[15] - m[12];
7956 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7957 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7958 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7959 r_refdef.view.frustum[1].dist = m[15] + m[12];
7961 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7962 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7963 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7964 r_refdef.view.frustum[2].dist = m[15] - m[13];
7966 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7967 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7968 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7969 r_refdef.view.frustum[3].dist = m[15] + m[13];
7971 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7972 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7973 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7974 r_refdef.view.frustum[4].dist = m[15] - m[14];
7976 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7977 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7978 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7979 r_refdef.view.frustum[5].dist = m[15] + m[14];
7982 if (r_refdef.view.useperspective)
7984 slopex = 1.0 / r_refdef.view.frustum_x;
7985 slopey = 1.0 / r_refdef.view.frustum_y;
7986 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7987 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
7988 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
7989 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
7990 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7992 // Leaving those out was a mistake, those were in the old code, and they
7993 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7994 // I couldn't reproduce it after adding those normalizations. --blub
7995 VectorNormalize(r_refdef.view.frustum[0].normal);
7996 VectorNormalize(r_refdef.view.frustum[1].normal);
7997 VectorNormalize(r_refdef.view.frustum[2].normal);
7998 VectorNormalize(r_refdef.view.frustum[3].normal);
8000 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8001 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]);
8002 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]);
8003 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]);
8004 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]);
8006 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8007 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8008 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8009 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8010 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8014 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8015 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8016 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8017 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8018 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8019 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8020 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8021 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8022 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8023 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8025 r_refdef.view.numfrustumplanes = 5;
8027 if (r_refdef.view.useclipplane)
8029 r_refdef.view.numfrustumplanes = 6;
8030 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8033 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8034 PlaneClassify(r_refdef.view.frustum + i);
8036 // LordHavoc: note to all quake engine coders, Quake had a special case
8037 // for 90 degrees which assumed a square view (wrong), so I removed it,
8038 // Quake2 has it disabled as well.
8040 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8041 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8042 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8043 //PlaneClassify(&frustum[0]);
8045 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8046 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8047 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8048 //PlaneClassify(&frustum[1]);
8050 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8051 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8052 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8053 //PlaneClassify(&frustum[2]);
8055 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8056 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8057 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8058 //PlaneClassify(&frustum[3]);
8061 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8062 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8063 //PlaneClassify(&frustum[4]);
8066 void R_View_Update(void)
8068 R_Main_ResizeViewCache();
8069 R_View_SetFrustum();
8070 R_View_WorldVisibility(r_refdef.view.useclipplane);
8071 R_View_UpdateEntityVisible();
8072 R_View_UpdateEntityLighting();
8075 void R_SetupView(qboolean allowwaterclippingplane)
8077 const float *customclipplane = NULL;
8079 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8081 // LordHavoc: couldn't figure out how to make this approach the
8082 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8083 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8084 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8085 dist = r_refdef.view.clipplane.dist;
8086 plane[0] = r_refdef.view.clipplane.normal[0];
8087 plane[1] = r_refdef.view.clipplane.normal[1];
8088 plane[2] = r_refdef.view.clipplane.normal[2];
8090 customclipplane = plane;
8093 if (!r_refdef.view.useperspective)
8094 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);
8095 else if (vid.stencil && r_useinfinitefarclip.integer)
8096 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);
8098 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);
8099 R_SetViewport(&r_refdef.view.viewport);
8102 void R_EntityMatrix(const matrix4x4_t *matrix)
8104 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8106 gl_modelmatrixchanged = false;
8107 gl_modelmatrix = *matrix;
8108 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8109 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8110 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8111 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8113 switch(vid.renderpath)
8115 case RENDERPATH_D3D9:
8117 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8118 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8121 case RENDERPATH_D3D10:
8122 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8124 case RENDERPATH_D3D11:
8125 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8127 case RENDERPATH_GL20:
8128 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8129 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8130 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8132 case RENDERPATH_CGGL:
8135 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8136 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8137 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8140 case RENDERPATH_GL13:
8141 case RENDERPATH_GL11:
8142 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8148 void R_ResetViewRendering2D(void)
8150 r_viewport_t viewport;
8153 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8154 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);
8155 R_SetViewport(&viewport);
8156 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8157 GL_Color(1, 1, 1, 1);
8158 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8159 GL_BlendFunc(GL_ONE, GL_ZERO);
8160 GL_AlphaTest(false);
8161 GL_ScissorTest(false);
8162 GL_DepthMask(false);
8163 GL_DepthRange(0, 1);
8164 GL_DepthTest(false);
8165 GL_DepthFunc(GL_LEQUAL);
8166 R_EntityMatrix(&identitymatrix);
8167 R_Mesh_ResetTextureState();
8168 GL_PolygonOffset(0, 0);
8169 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8170 switch(vid.renderpath)
8172 case RENDERPATH_GL11:
8173 case RENDERPATH_GL13:
8174 case RENDERPATH_GL20:
8175 case RENDERPATH_CGGL:
8176 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8178 case RENDERPATH_D3D9:
8179 case RENDERPATH_D3D10:
8180 case RENDERPATH_D3D11:
8183 GL_CullFace(GL_NONE);
8186 void R_ResetViewRendering3D(void)
8191 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8192 GL_Color(1, 1, 1, 1);
8193 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8194 GL_BlendFunc(GL_ONE, GL_ZERO);
8195 GL_AlphaTest(false);
8196 GL_ScissorTest(true);
8198 GL_DepthRange(0, 1);
8200 GL_DepthFunc(GL_LEQUAL);
8201 R_EntityMatrix(&identitymatrix);
8202 R_Mesh_ResetTextureState();
8203 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8204 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8205 switch(vid.renderpath)
8207 case RENDERPATH_GL11:
8208 case RENDERPATH_GL13:
8209 case RENDERPATH_GL20:
8210 case RENDERPATH_CGGL:
8211 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8213 case RENDERPATH_D3D9:
8214 case RENDERPATH_D3D10:
8215 case RENDERPATH_D3D11:
8218 GL_CullFace(r_refdef.view.cullface_back);
8223 R_RenderView_UpdateViewVectors
8226 static void R_RenderView_UpdateViewVectors(void)
8228 // break apart the view matrix into vectors for various purposes
8229 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8230 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8231 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8232 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8233 // make an inverted copy of the view matrix for tracking sprites
8234 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8237 void R_RenderScene(void);
8238 void R_RenderWaterPlanes(void);
8240 static void R_Water_StartFrame(void)
8243 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8244 r_waterstate_waterplane_t *p;
8246 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8249 switch(vid.renderpath)
8251 case RENDERPATH_GL20:
8252 case RENDERPATH_CGGL:
8253 case RENDERPATH_D3D9:
8254 case RENDERPATH_D3D10:
8255 case RENDERPATH_D3D11:
8257 case RENDERPATH_GL13:
8258 case RENDERPATH_GL11:
8262 // set waterwidth and waterheight to the water resolution that will be
8263 // used (often less than the screen resolution for faster rendering)
8264 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8265 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8267 // calculate desired texture sizes
8268 // can't use water if the card does not support the texture size
8269 if (!r_water.integer || r_showsurfaces.integer)
8270 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8271 else if (vid.support.arb_texture_non_power_of_two)
8273 texturewidth = waterwidth;
8274 textureheight = waterheight;
8275 camerawidth = waterwidth;
8276 cameraheight = waterheight;
8280 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8281 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8282 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8283 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8286 // allocate textures as needed
8287 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8289 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8290 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8292 if (p->texture_refraction)
8293 R_FreeTexture(p->texture_refraction);
8294 p->texture_refraction = NULL;
8295 if (p->texture_reflection)
8296 R_FreeTexture(p->texture_reflection);
8297 p->texture_reflection = NULL;
8298 if (p->texture_camera)
8299 R_FreeTexture(p->texture_camera);
8300 p->texture_camera = NULL;
8302 memset(&r_waterstate, 0, sizeof(r_waterstate));
8303 r_waterstate.texturewidth = texturewidth;
8304 r_waterstate.textureheight = textureheight;
8305 r_waterstate.camerawidth = camerawidth;
8306 r_waterstate.cameraheight = cameraheight;
8309 if (r_waterstate.texturewidth)
8311 r_waterstate.enabled = true;
8313 // when doing a reduced render (HDR) we want to use a smaller area
8314 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8315 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8317 // set up variables that will be used in shader setup
8318 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8319 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8320 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8321 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8324 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8325 r_waterstate.numwaterplanes = 0;
8328 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8330 int triangleindex, planeindex;
8337 r_waterstate_waterplane_t *p;
8338 texture_t *t = R_GetCurrentTexture(surface->texture);
8339 cam_ent = t->camera_entity;
8340 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8343 // just use the first triangle with a valid normal for any decisions
8344 VectorClear(normal);
8345 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8347 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8348 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8349 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8350 TriangleNormal(vert[0], vert[1], vert[2], normal);
8351 if (VectorLength2(normal) >= 0.001)
8355 VectorCopy(normal, plane.normal);
8356 VectorNormalize(plane.normal);
8357 plane.dist = DotProduct(vert[0], plane.normal);
8358 PlaneClassify(&plane);
8359 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8361 // skip backfaces (except if nocullface is set)
8362 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8364 VectorNegate(plane.normal, plane.normal);
8366 PlaneClassify(&plane);
8370 // find a matching plane if there is one
8371 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8372 if(p->camera_entity == t->camera_entity)
8373 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8375 if (planeindex >= r_waterstate.maxwaterplanes)
8376 return; // nothing we can do, out of planes
8378 // if this triangle does not fit any known plane rendered this frame, add one
8379 if (planeindex >= r_waterstate.numwaterplanes)
8381 // store the new plane
8382 r_waterstate.numwaterplanes++;
8384 // clear materialflags and pvs
8385 p->materialflags = 0;
8386 p->pvsvalid = false;
8387 p->camera_entity = t->camera_entity;
8389 // merge this surface's materialflags into the waterplane
8390 p->materialflags |= t->currentmaterialflags;
8391 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8393 // merge this surface's PVS into the waterplane
8394 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8395 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8396 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8398 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8404 static void R_Water_ProcessPlanes(void)
8406 r_refdef_view_t originalview;
8407 r_refdef_view_t myview;
8409 r_waterstate_waterplane_t *p;
8412 originalview = r_refdef.view;
8414 // make sure enough textures are allocated
8415 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8417 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8419 if (!p->texture_refraction)
8420 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);
8421 if (!p->texture_refraction)
8424 else if (p->materialflags & MATERIALFLAG_CAMERA)
8426 if (!p->texture_camera)
8427 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);
8428 if (!p->texture_camera)
8432 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8434 if (!p->texture_reflection)
8435 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);
8436 if (!p->texture_reflection)
8442 r_refdef.view = originalview;
8443 r_refdef.view.showdebug = false;
8444 r_refdef.view.width = r_waterstate.waterwidth;
8445 r_refdef.view.height = r_waterstate.waterheight;
8446 r_refdef.view.useclipplane = true;
8447 myview = r_refdef.view;
8448 r_waterstate.renderingscene = true;
8449 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8451 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8453 r_refdef.view = myview;
8454 // render reflected scene and copy into texture
8455 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8456 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8457 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8458 r_refdef.view.clipplane = p->plane;
8459 // reverse the cullface settings for this render
8460 r_refdef.view.cullface_front = GL_FRONT;
8461 r_refdef.view.cullface_back = GL_BACK;
8462 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8464 r_refdef.view.usecustompvs = true;
8466 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8468 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8471 R_ResetViewRendering3D();
8472 R_ClearScreen(r_refdef.fogenabled);
8476 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);
8479 // render the normal view scene and copy into texture
8480 // (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)
8481 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8483 r_waterstate.renderingrefraction = true;
8484 r_refdef.view = myview;
8486 r_refdef.view.clipplane = p->plane;
8487 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8488 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8490 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8492 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8493 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8494 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8495 R_RenderView_UpdateViewVectors();
8496 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8498 r_refdef.view.usecustompvs = true;
8499 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);
8503 PlaneClassify(&r_refdef.view.clipplane);
8505 R_ResetViewRendering3D();
8506 R_ClearScreen(r_refdef.fogenabled);
8510 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);
8511 r_waterstate.renderingrefraction = false;
8513 else if (p->materialflags & MATERIALFLAG_CAMERA)
8515 r_refdef.view = myview;
8517 r_refdef.view.clipplane = p->plane;
8518 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8519 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8521 r_refdef.view.width = r_waterstate.camerawidth;
8522 r_refdef.view.height = r_waterstate.cameraheight;
8523 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8524 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8526 if(p->camera_entity)
8528 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8529 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8532 // reverse the cullface settings for this render
8533 r_refdef.view.cullface_front = GL_FRONT;
8534 r_refdef.view.cullface_back = GL_BACK;
8535 // also reverse the view matrix
8536 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
8537 R_RenderView_UpdateViewVectors();
8538 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8540 r_refdef.view.usecustompvs = true;
8541 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);
8544 // camera needs no clipplane
8545 r_refdef.view.useclipplane = false;
8547 PlaneClassify(&r_refdef.view.clipplane);
8549 R_ResetViewRendering3D();
8550 R_ClearScreen(r_refdef.fogenabled);
8554 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);
8555 r_waterstate.renderingrefraction = false;
8559 r_waterstate.renderingscene = false;
8560 r_refdef.view = originalview;
8561 R_ResetViewRendering3D();
8562 R_ClearScreen(r_refdef.fogenabled);
8566 r_refdef.view = originalview;
8567 r_waterstate.renderingscene = false;
8568 Cvar_SetValueQuick(&r_water, 0);
8569 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8573 void R_Bloom_StartFrame(void)
8575 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8577 switch(vid.renderpath)
8579 case RENDERPATH_GL20:
8580 case RENDERPATH_CGGL:
8581 case RENDERPATH_D3D9:
8582 case RENDERPATH_D3D10:
8583 case RENDERPATH_D3D11:
8585 case RENDERPATH_GL13:
8586 case RENDERPATH_GL11:
8590 // set bloomwidth and bloomheight to the bloom resolution that will be
8591 // used (often less than the screen resolution for faster rendering)
8592 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8593 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8594 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8595 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8596 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8598 // calculate desired texture sizes
8599 if (vid.support.arb_texture_non_power_of_two)
8601 screentexturewidth = r_refdef.view.width;
8602 screentextureheight = r_refdef.view.height;
8603 bloomtexturewidth = r_bloomstate.bloomwidth;
8604 bloomtextureheight = r_bloomstate.bloomheight;
8608 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8609 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8610 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8611 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8614 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))
8616 Cvar_SetValueQuick(&r_hdr, 0);
8617 Cvar_SetValueQuick(&r_bloom, 0);
8618 Cvar_SetValueQuick(&r_motionblur, 0);
8619 Cvar_SetValueQuick(&r_damageblur, 0);
8622 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)))
8623 screentexturewidth = screentextureheight = 0;
8624 if (!r_hdr.integer && !r_bloom.integer)
8625 bloomtexturewidth = bloomtextureheight = 0;
8627 // allocate textures as needed
8628 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8630 if (r_bloomstate.texture_screen)
8631 R_FreeTexture(r_bloomstate.texture_screen);
8632 r_bloomstate.texture_screen = NULL;
8633 r_bloomstate.screentexturewidth = screentexturewidth;
8634 r_bloomstate.screentextureheight = screentextureheight;
8635 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8636 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);
8638 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8640 if (r_bloomstate.texture_bloom)
8641 R_FreeTexture(r_bloomstate.texture_bloom);
8642 r_bloomstate.texture_bloom = NULL;
8643 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8644 r_bloomstate.bloomtextureheight = bloomtextureheight;
8645 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8646 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);
8649 // when doing a reduced render (HDR) we want to use a smaller area
8650 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8651 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8652 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8653 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8654 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8656 // set up a texcoord array for the full resolution screen image
8657 // (we have to keep this around to copy back during final render)
8658 r_bloomstate.screentexcoord2f[0] = 0;
8659 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8660 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8661 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8662 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8663 r_bloomstate.screentexcoord2f[5] = 0;
8664 r_bloomstate.screentexcoord2f[6] = 0;
8665 r_bloomstate.screentexcoord2f[7] = 0;
8667 // set up a texcoord array for the reduced resolution bloom image
8668 // (which will be additive blended over the screen image)
8669 r_bloomstate.bloomtexcoord2f[0] = 0;
8670 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8671 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8672 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8673 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8674 r_bloomstate.bloomtexcoord2f[5] = 0;
8675 r_bloomstate.bloomtexcoord2f[6] = 0;
8676 r_bloomstate.bloomtexcoord2f[7] = 0;
8678 switch(vid.renderpath)
8680 case RENDERPATH_GL11:
8681 case RENDERPATH_GL13:
8682 case RENDERPATH_GL20:
8683 case RENDERPATH_CGGL:
8685 case RENDERPATH_D3D9:
8686 case RENDERPATH_D3D10:
8687 case RENDERPATH_D3D11:
8690 for (i = 0;i < 4;i++)
8692 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8693 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8694 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8695 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8701 if (r_hdr.integer || r_bloom.integer)
8703 r_bloomstate.enabled = true;
8704 r_bloomstate.hdr = r_hdr.integer != 0;
8707 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);
8710 void R_Bloom_CopyBloomTexture(float colorscale)
8712 r_refdef.stats.bloom++;
8714 // scale down screen texture to the bloom texture size
8716 R_SetViewport(&r_bloomstate.viewport);
8717 GL_BlendFunc(GL_ONE, GL_ZERO);
8718 GL_Color(colorscale, colorscale, colorscale, 1);
8719 // 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...
8720 switch(vid.renderpath)
8722 case RENDERPATH_GL11:
8723 case RENDERPATH_GL13:
8724 case RENDERPATH_GL20:
8725 case RENDERPATH_CGGL:
8726 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8728 case RENDERPATH_D3D9:
8729 case RENDERPATH_D3D10:
8730 case RENDERPATH_D3D11:
8731 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8734 // TODO: do boxfilter scale-down in shader?
8735 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8736 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8737 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8739 // we now have a bloom image in the framebuffer
8740 // copy it into the bloom image texture for later processing
8741 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);
8742 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8745 void R_Bloom_CopyHDRTexture(void)
8747 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);
8748 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8751 void R_Bloom_MakeTexture(void)
8754 float xoffset, yoffset, r, brighten;
8756 r_refdef.stats.bloom++;
8758 R_ResetViewRendering2D();
8760 // we have a bloom image in the framebuffer
8762 R_SetViewport(&r_bloomstate.viewport);
8764 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8767 r = bound(0, r_bloom_colorexponent.value / x, 1);
8768 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8770 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8771 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8772 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8773 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8775 // copy the vertically blurred bloom view to a texture
8776 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);
8777 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8780 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8781 brighten = r_bloom_brighten.value;
8783 brighten *= r_hdr_range.value;
8784 brighten = sqrt(brighten);
8786 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8787 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8789 for (dir = 0;dir < 2;dir++)
8791 // blend on at multiple vertical offsets to achieve a vertical blur
8792 // TODO: do offset blends using GLSL
8793 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8794 GL_BlendFunc(GL_ONE, GL_ZERO);
8795 for (x = -range;x <= range;x++)
8797 if (!dir){xoffset = 0;yoffset = x;}
8798 else {xoffset = x;yoffset = 0;}
8799 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8800 yoffset /= (float)r_bloomstate.bloomtextureheight;
8801 // compute a texcoord array with the specified x and y offset
8802 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8803 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8804 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8805 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8806 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8807 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8808 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8809 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8810 // this r value looks like a 'dot' particle, fading sharply to
8811 // black at the edges
8812 // (probably not realistic but looks good enough)
8813 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8814 //r = brighten/(range*2+1);
8815 r = brighten / (range * 2 + 1);
8817 r *= (1 - x*x/(float)(range*range));
8818 GL_Color(r, r, r, 1);
8819 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8820 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8821 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8822 GL_BlendFunc(GL_ONE, GL_ONE);
8825 // copy the vertically blurred bloom view to a texture
8826 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);
8827 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8831 void R_HDR_RenderBloomTexture(void)
8833 int oldwidth, oldheight;
8834 float oldcolorscale;
8836 oldcolorscale = r_refdef.view.colorscale;
8837 oldwidth = r_refdef.view.width;
8838 oldheight = r_refdef.view.height;
8839 r_refdef.view.width = r_bloomstate.bloomwidth;
8840 r_refdef.view.height = r_bloomstate.bloomheight;
8842 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8843 // TODO: add exposure compensation features
8844 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8846 r_refdef.view.showdebug = false;
8847 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8849 R_ResetViewRendering3D();
8851 R_ClearScreen(r_refdef.fogenabled);
8852 if (r_timereport_active)
8853 R_TimeReport("HDRclear");
8856 if (r_timereport_active)
8857 R_TimeReport("visibility");
8859 // only do secondary renders with HDR if r_hdr is 2 or higher
8860 r_waterstate.numwaterplanes = 0;
8861 if (r_waterstate.enabled && r_hdr.integer >= 2)
8862 R_RenderWaterPlanes();
8864 r_refdef.view.showdebug = true;
8866 r_waterstate.numwaterplanes = 0;
8868 R_ResetViewRendering2D();
8870 R_Bloom_CopyHDRTexture();
8871 R_Bloom_MakeTexture();
8873 // restore the view settings
8874 r_refdef.view.width = oldwidth;
8875 r_refdef.view.height = oldheight;
8876 r_refdef.view.colorscale = oldcolorscale;
8878 R_ResetViewRendering3D();
8880 R_ClearScreen(r_refdef.fogenabled);
8881 if (r_timereport_active)
8882 R_TimeReport("viewclear");
8885 static void R_BlendView(void)
8887 unsigned int permutation;
8888 float uservecs[4][4];
8890 switch (vid.renderpath)
8892 case RENDERPATH_GL20:
8893 case RENDERPATH_CGGL:
8894 case RENDERPATH_D3D9:
8895 case RENDERPATH_D3D10:
8896 case RENDERPATH_D3D11:
8898 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8899 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8900 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8901 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8902 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8904 if (r_bloomstate.texture_screen)
8906 // make sure the buffer is available
8907 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8909 R_ResetViewRendering2D();
8911 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8913 // declare variables
8915 static float avgspeed;
8917 speed = VectorLength(cl.movement_velocity);
8919 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8920 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8922 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8923 speed = bound(0, speed, 1);
8924 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8926 // calculate values into a standard alpha
8927 cl.motionbluralpha = 1 - exp(-
8929 (r_motionblur.value * speed / 80)
8931 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8934 max(0.0001, cl.time - cl.oldtime) // fps independent
8937 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8938 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8940 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8942 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8943 GL_Color(1, 1, 1, cl.motionbluralpha);
8944 switch(vid.renderpath)
8946 case RENDERPATH_GL11:
8947 case RENDERPATH_GL13:
8948 case RENDERPATH_GL20:
8949 case RENDERPATH_CGGL:
8950 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8952 case RENDERPATH_D3D9:
8953 case RENDERPATH_D3D10:
8954 case RENDERPATH_D3D11:
8955 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8958 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8959 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8960 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8964 // copy view into the screen texture
8965 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);
8966 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8968 else if (!r_bloomstate.texture_bloom)
8970 // we may still have to do view tint...
8971 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8973 // apply a color tint to the whole view
8974 R_ResetViewRendering2D();
8975 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8976 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8977 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8978 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8979 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8981 break; // no screen processing, no bloom, skip it
8984 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8986 // render simple bloom effect
8987 // copy the screen and shrink it and darken it for the bloom process
8988 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8989 // make the bloom texture
8990 R_Bloom_MakeTexture();
8993 #if _MSC_VER >= 1400
8994 #define sscanf sscanf_s
8996 memset(uservecs, 0, sizeof(uservecs));
8997 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8998 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8999 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9000 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9002 R_ResetViewRendering2D();
9003 GL_Color(1, 1, 1, 1);
9004 GL_BlendFunc(GL_ONE, GL_ZERO);
9006 switch(vid.renderpath)
9008 case RENDERPATH_GL20:
9009 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9010 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9011 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9012 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9013 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9014 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]);
9015 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9016 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]);
9017 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]);
9018 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]);
9019 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]);
9020 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9021 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9022 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);
9024 case RENDERPATH_CGGL:
9026 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9027 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9028 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9029 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9030 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9031 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
9032 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9033 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
9034 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
9035 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
9036 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
9037 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9038 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9039 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);
9042 case RENDERPATH_D3D9:
9044 // 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...
9045 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9046 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9047 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9048 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9049 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9050 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9051 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9052 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9053 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9054 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9055 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9056 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9057 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9058 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9061 case RENDERPATH_D3D10:
9062 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9064 case RENDERPATH_D3D11:
9065 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9070 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9071 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9073 case RENDERPATH_GL13:
9074 case RENDERPATH_GL11:
9075 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9077 // apply a color tint to the whole view
9078 R_ResetViewRendering2D();
9079 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9080 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9081 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9082 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9083 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9089 matrix4x4_t r_waterscrollmatrix;
9091 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9093 if (r_refdef.fog_density)
9095 r_refdef.fogcolor[0] = r_refdef.fog_red;
9096 r_refdef.fogcolor[1] = r_refdef.fog_green;
9097 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9099 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9100 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9101 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9102 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9106 VectorCopy(r_refdef.fogcolor, fogvec);
9107 // color.rgb *= ContrastBoost * SceneBrightness;
9108 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9109 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9110 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9111 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9116 void R_UpdateVariables(void)
9120 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9122 r_refdef.farclip = r_farclip_base.value;
9123 if (r_refdef.scene.worldmodel)
9124 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9125 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9127 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9128 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9129 r_refdef.polygonfactor = 0;
9130 r_refdef.polygonoffset = 0;
9131 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9132 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9134 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9135 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9136 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9137 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9138 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9139 if (r_showsurfaces.integer)
9141 r_refdef.scene.rtworld = false;
9142 r_refdef.scene.rtworldshadows = false;
9143 r_refdef.scene.rtdlight = false;
9144 r_refdef.scene.rtdlightshadows = false;
9145 r_refdef.lightmapintensity = 0;
9148 if (gamemode == GAME_NEHAHRA)
9150 if (gl_fogenable.integer)
9152 r_refdef.oldgl_fogenable = true;
9153 r_refdef.fog_density = gl_fogdensity.value;
9154 r_refdef.fog_red = gl_fogred.value;
9155 r_refdef.fog_green = gl_foggreen.value;
9156 r_refdef.fog_blue = gl_fogblue.value;
9157 r_refdef.fog_alpha = 1;
9158 r_refdef.fog_start = 0;
9159 r_refdef.fog_end = gl_skyclip.value;
9160 r_refdef.fog_height = 1<<30;
9161 r_refdef.fog_fadedepth = 128;
9163 else if (r_refdef.oldgl_fogenable)
9165 r_refdef.oldgl_fogenable = false;
9166 r_refdef.fog_density = 0;
9167 r_refdef.fog_red = 0;
9168 r_refdef.fog_green = 0;
9169 r_refdef.fog_blue = 0;
9170 r_refdef.fog_alpha = 0;
9171 r_refdef.fog_start = 0;
9172 r_refdef.fog_end = 0;
9173 r_refdef.fog_height = 1<<30;
9174 r_refdef.fog_fadedepth = 128;
9178 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9179 r_refdef.fog_start = max(0, r_refdef.fog_start);
9180 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9182 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9184 if (r_refdef.fog_density && r_drawfog.integer)
9186 r_refdef.fogenabled = true;
9187 // this is the point where the fog reaches 0.9986 alpha, which we
9188 // consider a good enough cutoff point for the texture
9189 // (0.9986 * 256 == 255.6)
9190 if (r_fog_exp2.integer)
9191 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9193 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9194 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9195 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9196 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9197 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9198 R_BuildFogHeightTexture();
9199 // fog color was already set
9200 // update the fog texture
9201 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)
9202 R_BuildFogTexture();
9203 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9204 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9207 r_refdef.fogenabled = false;
9209 switch(vid.renderpath)
9211 case RENDERPATH_GL20:
9212 case RENDERPATH_CGGL:
9213 case RENDERPATH_D3D9:
9214 case RENDERPATH_D3D10:
9215 case RENDERPATH_D3D11:
9216 if(v_glslgamma.integer && !vid_gammatables_trivial)
9218 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9220 // build GLSL gamma texture
9221 #define RAMPWIDTH 256
9222 unsigned short ramp[RAMPWIDTH * 3];
9223 unsigned char rampbgr[RAMPWIDTH][4];
9226 r_texture_gammaramps_serial = vid_gammatables_serial;
9228 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9229 for(i = 0; i < RAMPWIDTH; ++i)
9231 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9232 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9233 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9236 if (r_texture_gammaramps)
9238 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9242 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9248 // remove GLSL gamma texture
9251 case RENDERPATH_GL13:
9252 case RENDERPATH_GL11:
9257 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9258 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9264 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9265 if( scenetype != r_currentscenetype ) {
9266 // store the old scenetype
9267 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9268 r_currentscenetype = scenetype;
9269 // move in the new scene
9270 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9279 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9281 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9282 if( scenetype == r_currentscenetype ) {
9283 return &r_refdef.scene;
9285 return &r_scenes_store[ scenetype ];
9294 void R_RenderView(void)
9296 if (r_timereport_active)
9297 R_TimeReport("start");
9298 r_textureframe++; // used only by R_GetCurrentTexture
9299 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9301 if (!r_drawentities.integer)
9302 r_refdef.scene.numentities = 0;
9304 R_AnimCache_ClearCache();
9305 R_FrameData_NewFrame();
9307 if (r_refdef.view.isoverlay)
9309 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9310 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9311 R_TimeReport("depthclear");
9313 r_refdef.view.showdebug = false;
9315 r_waterstate.enabled = false;
9316 r_waterstate.numwaterplanes = 0;
9324 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9325 return; //Host_Error ("R_RenderView: NULL worldmodel");
9327 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9329 R_RenderView_UpdateViewVectors();
9331 R_Shadow_UpdateWorldLightSelection();
9333 R_Bloom_StartFrame();
9334 R_Water_StartFrame();
9337 if (r_timereport_active)
9338 R_TimeReport("viewsetup");
9340 R_ResetViewRendering3D();
9342 if (r_refdef.view.clear || r_refdef.fogenabled)
9344 R_ClearScreen(r_refdef.fogenabled);
9345 if (r_timereport_active)
9346 R_TimeReport("viewclear");
9348 r_refdef.view.clear = true;
9350 // this produces a bloom texture to be used in R_BlendView() later
9351 if (r_hdr.integer && r_bloomstate.bloomwidth)
9353 R_HDR_RenderBloomTexture();
9354 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9355 r_textureframe++; // used only by R_GetCurrentTexture
9358 r_refdef.view.showdebug = true;
9361 if (r_timereport_active)
9362 R_TimeReport("visibility");
9364 r_waterstate.numwaterplanes = 0;
9365 if (r_waterstate.enabled)
9366 R_RenderWaterPlanes();
9369 r_waterstate.numwaterplanes = 0;
9372 if (r_timereport_active)
9373 R_TimeReport("blendview");
9375 GL_Scissor(0, 0, vid.width, vid.height);
9376 GL_ScissorTest(false);
9380 void R_RenderWaterPlanes(void)
9382 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9384 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9385 if (r_timereport_active)
9386 R_TimeReport("waterworld");
9389 // don't let sound skip if going slow
9390 if (r_refdef.scene.extraupdate)
9393 R_DrawModelsAddWaterPlanes();
9394 if (r_timereport_active)
9395 R_TimeReport("watermodels");
9397 if (r_waterstate.numwaterplanes)
9399 R_Water_ProcessPlanes();
9400 if (r_timereport_active)
9401 R_TimeReport("waterscenes");
9405 extern void R_DrawLightningBeams (void);
9406 extern void VM_CL_AddPolygonsToMeshQueue (void);
9407 extern void R_DrawPortals (void);
9408 extern cvar_t cl_locs_show;
9409 static void R_DrawLocs(void);
9410 static void R_DrawEntityBBoxes(void);
9411 static void R_DrawModelDecals(void);
9412 extern void R_DrawModelShadows(void);
9413 extern void R_DrawModelShadowMaps(void);
9414 extern cvar_t cl_decals_newsystem;
9415 extern qboolean r_shadow_usingdeferredprepass;
9416 void R_RenderScene(void)
9418 qboolean shadowmapping = false;
9420 if (r_timereport_active)
9421 R_TimeReport("beginscene");
9423 r_refdef.stats.renders++;
9427 // don't let sound skip if going slow
9428 if (r_refdef.scene.extraupdate)
9431 R_MeshQueue_BeginScene();
9435 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);
9437 if (r_timereport_active)
9438 R_TimeReport("skystartframe");
9440 if (cl.csqc_vidvars.drawworld)
9442 // don't let sound skip if going slow
9443 if (r_refdef.scene.extraupdate)
9446 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9448 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9449 if (r_timereport_active)
9450 R_TimeReport("worldsky");
9453 if (R_DrawBrushModelsSky() && r_timereport_active)
9454 R_TimeReport("bmodelsky");
9456 if (skyrendermasked && skyrenderlater)
9458 // we have to force off the water clipping plane while rendering sky
9462 if (r_timereport_active)
9463 R_TimeReport("sky");
9467 R_AnimCache_CacheVisibleEntities();
9468 if (r_timereport_active)
9469 R_TimeReport("animation");
9471 R_Shadow_PrepareLights();
9472 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9473 R_Shadow_PrepareModelShadows();
9474 if (r_timereport_active)
9475 R_TimeReport("preparelights");
9477 if (R_Shadow_ShadowMappingEnabled())
9478 shadowmapping = true;
9480 if (r_shadow_usingdeferredprepass)
9481 R_Shadow_DrawPrepass();
9483 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9485 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9486 if (r_timereport_active)
9487 R_TimeReport("worlddepth");
9489 if (r_depthfirst.integer >= 2)
9491 R_DrawModelsDepth();
9492 if (r_timereport_active)
9493 R_TimeReport("modeldepth");
9496 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9498 R_DrawModelShadowMaps();
9499 R_ResetViewRendering3D();
9500 // don't let sound skip if going slow
9501 if (r_refdef.scene.extraupdate)
9505 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9507 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9508 if (r_timereport_active)
9509 R_TimeReport("world");
9512 // don't let sound skip if going slow
9513 if (r_refdef.scene.extraupdate)
9517 if (r_timereport_active)
9518 R_TimeReport("models");
9520 // don't let sound skip if going slow
9521 if (r_refdef.scene.extraupdate)
9524 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9526 R_DrawModelShadows();
9527 R_ResetViewRendering3D();
9528 // don't let sound skip if going slow
9529 if (r_refdef.scene.extraupdate)
9533 if (!r_shadow_usingdeferredprepass)
9535 R_Shadow_DrawLights();
9536 if (r_timereport_active)
9537 R_TimeReport("rtlights");
9540 // don't let sound skip if going slow
9541 if (r_refdef.scene.extraupdate)
9544 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9546 R_DrawModelShadows();
9547 R_ResetViewRendering3D();
9548 // don't let sound skip if going slow
9549 if (r_refdef.scene.extraupdate)
9553 if (cl.csqc_vidvars.drawworld)
9555 if (cl_decals_newsystem.integer)
9557 R_DrawModelDecals();
9558 if (r_timereport_active)
9559 R_TimeReport("modeldecals");
9564 if (r_timereport_active)
9565 R_TimeReport("decals");
9569 if (r_timereport_active)
9570 R_TimeReport("particles");
9573 if (r_timereport_active)
9574 R_TimeReport("explosions");
9576 R_DrawLightningBeams();
9577 if (r_timereport_active)
9578 R_TimeReport("lightning");
9581 VM_CL_AddPolygonsToMeshQueue();
9583 if (r_refdef.view.showdebug)
9585 if (cl_locs_show.integer)
9588 if (r_timereport_active)
9589 R_TimeReport("showlocs");
9592 if (r_drawportals.integer)
9595 if (r_timereport_active)
9596 R_TimeReport("portals");
9599 if (r_showbboxes.value > 0)
9601 R_DrawEntityBBoxes();
9602 if (r_timereport_active)
9603 R_TimeReport("bboxes");
9607 R_MeshQueue_RenderTransparent();
9608 if (r_timereport_active)
9609 R_TimeReport("drawtrans");
9611 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))
9613 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9614 if (r_timereport_active)
9615 R_TimeReport("worlddebug");
9616 R_DrawModelsDebug();
9617 if (r_timereport_active)
9618 R_TimeReport("modeldebug");
9621 if (cl.csqc_vidvars.drawworld)
9623 R_Shadow_DrawCoronas();
9624 if (r_timereport_active)
9625 R_TimeReport("coronas");
9628 // don't let sound skip if going slow
9629 if (r_refdef.scene.extraupdate)
9632 R_ResetViewRendering2D();
9635 static const unsigned short bboxelements[36] =
9645 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9648 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9650 RSurf_ActiveWorldEntity();
9652 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9653 GL_DepthMask(false);
9654 GL_DepthRange(0, 1);
9655 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9656 R_Mesh_ResetTextureState();
9658 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9659 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9660 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9661 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9662 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9663 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9664 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9665 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9666 R_FillColors(color4f, 8, cr, cg, cb, ca);
9667 if (r_refdef.fogenabled)
9669 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9671 f1 = RSurf_FogVertex(v);
9673 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9674 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9675 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9678 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9679 R_Mesh_ResetTextureState();
9680 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9681 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9684 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9688 prvm_edict_t *edict;
9689 prvm_prog_t *prog_save = prog;
9691 // this function draws bounding boxes of server entities
9695 GL_CullFace(GL_NONE);
9696 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9700 for (i = 0;i < numsurfaces;i++)
9702 edict = PRVM_EDICT_NUM(surfacelist[i]);
9703 switch ((int)edict->fields.server->solid)
9705 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9706 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9707 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9708 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9709 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9710 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9712 color[3] *= r_showbboxes.value;
9713 color[3] = bound(0, color[3], 1);
9714 GL_DepthTest(!r_showdisabledepthtest.integer);
9715 GL_CullFace(r_refdef.view.cullface_front);
9716 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9722 static void R_DrawEntityBBoxes(void)
9725 prvm_edict_t *edict;
9727 prvm_prog_t *prog_save = prog;
9729 // this function draws bounding boxes of server entities
9735 for (i = 0;i < prog->num_edicts;i++)
9737 edict = PRVM_EDICT_NUM(i);
9738 if (edict->priv.server->free)
9740 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9741 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9743 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9745 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9746 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9752 static const int nomodelelement3i[24] =
9764 static const unsigned short nomodelelement3s[24] =
9776 static const float nomodelvertex3f[6*3] =
9786 static const float nomodelcolor4f[6*4] =
9788 0.0f, 0.0f, 0.5f, 1.0f,
9789 0.0f, 0.0f, 0.5f, 1.0f,
9790 0.0f, 0.5f, 0.0f, 1.0f,
9791 0.0f, 0.5f, 0.0f, 1.0f,
9792 0.5f, 0.0f, 0.0f, 1.0f,
9793 0.5f, 0.0f, 0.0f, 1.0f
9796 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9802 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);
9804 // this is only called once per entity so numsurfaces is always 1, and
9805 // surfacelist is always {0}, so this code does not handle batches
9807 if (rsurface.ent_flags & RENDER_ADDITIVE)
9809 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9810 GL_DepthMask(false);
9812 else if (rsurface.colormod[3] < 1)
9814 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9815 GL_DepthMask(false);
9819 GL_BlendFunc(GL_ONE, GL_ZERO);
9822 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9823 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9824 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9825 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9826 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9827 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9828 for (i = 0, c = color4f;i < 6;i++, c += 4)
9830 c[0] *= rsurface.colormod[0];
9831 c[1] *= rsurface.colormod[1];
9832 c[2] *= rsurface.colormod[2];
9833 c[3] *= rsurface.colormod[3];
9835 if (r_refdef.fogenabled)
9837 for (i = 0, c = color4f;i < 6;i++, c += 4)
9839 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9841 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9842 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9843 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9846 R_Mesh_ResetTextureState();
9847 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9848 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9851 void R_DrawNoModel(entity_render_t *ent)
9854 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9855 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9856 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9858 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9861 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9863 vec3_t right1, right2, diff, normal;
9865 VectorSubtract (org2, org1, normal);
9867 // calculate 'right' vector for start
9868 VectorSubtract (r_refdef.view.origin, org1, diff);
9869 CrossProduct (normal, diff, right1);
9870 VectorNormalize (right1);
9872 // calculate 'right' vector for end
9873 VectorSubtract (r_refdef.view.origin, org2, diff);
9874 CrossProduct (normal, diff, right2);
9875 VectorNormalize (right2);
9877 vert[ 0] = org1[0] + width * right1[0];
9878 vert[ 1] = org1[1] + width * right1[1];
9879 vert[ 2] = org1[2] + width * right1[2];
9880 vert[ 3] = org1[0] - width * right1[0];
9881 vert[ 4] = org1[1] - width * right1[1];
9882 vert[ 5] = org1[2] - width * right1[2];
9883 vert[ 6] = org2[0] - width * right2[0];
9884 vert[ 7] = org2[1] - width * right2[1];
9885 vert[ 8] = org2[2] - width * right2[2];
9886 vert[ 9] = org2[0] + width * right2[0];
9887 vert[10] = org2[1] + width * right2[1];
9888 vert[11] = org2[2] + width * right2[2];
9891 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)
9893 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9894 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9895 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9896 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9897 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9898 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9899 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9900 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9901 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9902 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9903 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9904 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9907 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9912 VectorSet(v, x, y, z);
9913 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9914 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9916 if (i == mesh->numvertices)
9918 if (mesh->numvertices < mesh->maxvertices)
9920 VectorCopy(v, vertex3f);
9921 mesh->numvertices++;
9923 return mesh->numvertices;
9929 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9933 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9934 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9935 e = mesh->element3i + mesh->numtriangles * 3;
9936 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9938 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9939 if (mesh->numtriangles < mesh->maxtriangles)
9944 mesh->numtriangles++;
9946 element[1] = element[2];
9950 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9954 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9955 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9956 e = mesh->element3i + mesh->numtriangles * 3;
9957 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9959 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9960 if (mesh->numtriangles < mesh->maxtriangles)
9965 mesh->numtriangles++;
9967 element[1] = element[2];
9971 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9972 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9974 int planenum, planenum2;
9977 mplane_t *plane, *plane2;
9979 double temppoints[2][256*3];
9980 // figure out how large a bounding box we need to properly compute this brush
9982 for (w = 0;w < numplanes;w++)
9983 maxdist = max(maxdist, fabs(planes[w].dist));
9984 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9985 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9986 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9990 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9991 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9993 if (planenum2 == planenum)
9995 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);
9998 if (tempnumpoints < 3)
10000 // generate elements forming a triangle fan for this polygon
10001 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10005 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)
10007 texturelayer_t *layer;
10008 layer = t->currentlayers + t->currentnumlayers++;
10009 layer->type = type;
10010 layer->depthmask = depthmask;
10011 layer->blendfunc1 = blendfunc1;
10012 layer->blendfunc2 = blendfunc2;
10013 layer->texture = texture;
10014 layer->texmatrix = *matrix;
10015 layer->color[0] = r;
10016 layer->color[1] = g;
10017 layer->color[2] = b;
10018 layer->color[3] = a;
10021 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10023 if(parms[0] == 0 && parms[1] == 0)
10025 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10026 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10031 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10034 index = parms[2] + r_refdef.scene.time * parms[3];
10035 index -= floor(index);
10036 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10039 case Q3WAVEFUNC_NONE:
10040 case Q3WAVEFUNC_NOISE:
10041 case Q3WAVEFUNC_COUNT:
10044 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10045 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10046 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10047 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10048 case Q3WAVEFUNC_TRIANGLE:
10050 f = index - floor(index);
10053 else if (index < 2)
10055 else if (index < 3)
10061 f = parms[0] + parms[1] * f;
10062 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10063 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10067 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10072 matrix4x4_t matrix, temp;
10073 switch(tcmod->tcmod)
10075 case Q3TCMOD_COUNT:
10077 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10078 matrix = r_waterscrollmatrix;
10080 matrix = identitymatrix;
10082 case Q3TCMOD_ENTITYTRANSLATE:
10083 // this is used in Q3 to allow the gamecode to control texcoord
10084 // scrolling on the entity, which is not supported in darkplaces yet.
10085 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10087 case Q3TCMOD_ROTATE:
10088 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10089 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10090 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10092 case Q3TCMOD_SCALE:
10093 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10095 case Q3TCMOD_SCROLL:
10096 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10098 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10099 w = (int) tcmod->parms[0];
10100 h = (int) tcmod->parms[1];
10101 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10103 idx = (int) floor(f * w * h);
10104 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10106 case Q3TCMOD_STRETCH:
10107 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10108 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10110 case Q3TCMOD_TRANSFORM:
10111 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10112 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10113 VectorSet(tcmat + 6, 0 , 0 , 1);
10114 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10115 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10117 case Q3TCMOD_TURBULENT:
10118 // this is handled in the RSurf_PrepareVertices function
10119 matrix = identitymatrix;
10123 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10126 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10128 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10129 char name[MAX_QPATH];
10130 skinframe_t *skinframe;
10131 unsigned char pixels[296*194];
10132 strlcpy(cache->name, skinname, sizeof(cache->name));
10133 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10134 if (developer_loading.integer)
10135 Con_Printf("loading %s\n", name);
10136 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10137 if (!skinframe || !skinframe->base)
10140 fs_offset_t filesize;
10142 f = FS_LoadFile(name, tempmempool, true, &filesize);
10145 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10146 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10150 cache->skinframe = skinframe;
10153 texture_t *R_GetCurrentTexture(texture_t *t)
10156 const entity_render_t *ent = rsurface.entity;
10157 dp_model_t *model = ent->model;
10158 q3shaderinfo_layer_tcmod_t *tcmod;
10160 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10161 return t->currentframe;
10162 t->update_lastrenderframe = r_textureframe;
10163 t->update_lastrenderentity = (void *)ent;
10165 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10166 t->camera_entity = ent->entitynumber;
10168 t->camera_entity = 0;
10170 // switch to an alternate material if this is a q1bsp animated material
10172 texture_t *texture = t;
10173 int s = rsurface.ent_skinnum;
10174 if ((unsigned int)s >= (unsigned int)model->numskins)
10176 if (model->skinscenes)
10178 if (model->skinscenes[s].framecount > 1)
10179 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10181 s = model->skinscenes[s].firstframe;
10184 t = t + s * model->num_surfaces;
10187 // use an alternate animation if the entity's frame is not 0,
10188 // and only if the texture has an alternate animation
10189 if (rsurface.ent_alttextures && t->anim_total[1])
10190 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10192 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10194 texture->currentframe = t;
10197 // update currentskinframe to be a qw skin or animation frame
10198 if (rsurface.ent_qwskin >= 0)
10200 i = rsurface.ent_qwskin;
10201 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10203 r_qwskincache_size = cl.maxclients;
10205 Mem_Free(r_qwskincache);
10206 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10208 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10209 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10210 t->currentskinframe = r_qwskincache[i].skinframe;
10211 if (t->currentskinframe == NULL)
10212 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10214 else if (t->numskinframes >= 2)
10215 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10216 if (t->backgroundnumskinframes >= 2)
10217 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10219 t->currentmaterialflags = t->basematerialflags;
10220 t->currentalpha = rsurface.colormod[3];
10221 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10222 t->currentalpha *= r_wateralpha.value;
10223 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10224 t->currentalpha *= t->r_water_wateralpha;
10225 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10226 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10227 if (!(rsurface.ent_flags & RENDER_LIGHT))
10228 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10229 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10231 // pick a model lighting mode
10232 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10233 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10235 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10237 if (rsurface.ent_flags & RENDER_ADDITIVE)
10238 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10239 else if (t->currentalpha < 1)
10240 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10241 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10242 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10243 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10244 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10245 if (t->backgroundnumskinframes)
10246 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10247 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10249 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10250 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10253 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10254 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10255 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10257 // there is no tcmod
10258 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10260 t->currenttexmatrix = r_waterscrollmatrix;
10261 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10263 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10265 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10266 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10269 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10270 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10271 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10272 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10274 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10275 if (t->currentskinframe->qpixels)
10276 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10277 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10278 if (!t->basetexture)
10279 t->basetexture = r_texture_notexture;
10280 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10281 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10282 t->nmaptexture = t->currentskinframe->nmap;
10283 if (!t->nmaptexture)
10284 t->nmaptexture = r_texture_blanknormalmap;
10285 t->glosstexture = r_texture_black;
10286 t->glowtexture = t->currentskinframe->glow;
10287 t->fogtexture = t->currentskinframe->fog;
10288 t->reflectmasktexture = t->currentskinframe->reflect;
10289 if (t->backgroundnumskinframes)
10291 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10292 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10293 t->backgroundglosstexture = r_texture_black;
10294 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10295 if (!t->backgroundnmaptexture)
10296 t->backgroundnmaptexture = r_texture_blanknormalmap;
10300 t->backgroundbasetexture = r_texture_white;
10301 t->backgroundnmaptexture = r_texture_blanknormalmap;
10302 t->backgroundglosstexture = r_texture_black;
10303 t->backgroundglowtexture = NULL;
10305 t->specularpower = r_shadow_glossexponent.value;
10306 // TODO: store reference values for these in the texture?
10307 t->specularscale = 0;
10308 if (r_shadow_gloss.integer > 0)
10310 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10312 if (r_shadow_glossintensity.value > 0)
10314 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10315 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10316 t->specularscale = r_shadow_glossintensity.value;
10319 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10321 t->glosstexture = r_texture_white;
10322 t->backgroundglosstexture = r_texture_white;
10323 t->specularscale = r_shadow_gloss2intensity.value;
10324 t->specularpower = r_shadow_gloss2exponent.value;
10327 t->specularscale *= t->specularscalemod;
10328 t->specularpower *= t->specularpowermod;
10330 // lightmaps mode looks bad with dlights using actual texturing, so turn
10331 // off the colormap and glossmap, but leave the normalmap on as it still
10332 // accurately represents the shading involved
10333 if (gl_lightmaps.integer)
10335 t->basetexture = r_texture_grey128;
10336 t->pantstexture = r_texture_black;
10337 t->shirttexture = r_texture_black;
10338 t->nmaptexture = r_texture_blanknormalmap;
10339 t->glosstexture = r_texture_black;
10340 t->glowtexture = NULL;
10341 t->fogtexture = NULL;
10342 t->reflectmasktexture = NULL;
10343 t->backgroundbasetexture = NULL;
10344 t->backgroundnmaptexture = r_texture_blanknormalmap;
10345 t->backgroundglosstexture = r_texture_black;
10346 t->backgroundglowtexture = NULL;
10347 t->specularscale = 0;
10348 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10351 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10352 VectorClear(t->dlightcolor);
10353 t->currentnumlayers = 0;
10354 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10356 int blendfunc1, blendfunc2;
10357 qboolean depthmask;
10358 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10360 blendfunc1 = GL_SRC_ALPHA;
10361 blendfunc2 = GL_ONE;
10363 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10365 blendfunc1 = GL_SRC_ALPHA;
10366 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10368 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10370 blendfunc1 = t->customblendfunc[0];
10371 blendfunc2 = t->customblendfunc[1];
10375 blendfunc1 = GL_ONE;
10376 blendfunc2 = GL_ZERO;
10378 // don't colormod evilblend textures
10379 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10380 VectorSet(t->lightmapcolor, 1, 1, 1);
10381 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10382 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10384 // fullbright is not affected by r_refdef.lightmapintensity
10385 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]);
10386 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10387 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]);
10388 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10389 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]);
10393 vec3_t ambientcolor;
10395 // set the color tint used for lights affecting this surface
10396 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10398 // q3bsp has no lightmap updates, so the lightstylevalue that
10399 // would normally be baked into the lightmap must be
10400 // applied to the color
10401 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10402 if (model->type == mod_brushq3)
10403 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10404 colorscale *= r_refdef.lightmapintensity;
10405 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10406 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10407 // basic lit geometry
10408 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]);
10409 // add pants/shirt if needed
10410 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10411 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]);
10412 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10413 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]);
10414 // now add ambient passes if needed
10415 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10417 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]);
10418 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10419 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]);
10420 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10421 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]);
10424 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10425 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]);
10426 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10428 // if this is opaque use alpha blend which will darken the earlier
10431 // if this is an alpha blended material, all the earlier passes
10432 // were darkened by fog already, so we only need to add the fog
10433 // color ontop through the fog mask texture
10435 // if this is an additive blended material, all the earlier passes
10436 // were darkened by fog already, and we should not add fog color
10437 // (because the background was not darkened, there is no fog color
10438 // that was lost behind it).
10439 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]);
10443 return t->currentframe;
10446 rsurfacestate_t rsurface;
10448 void R_Mesh_ResizeArrays(int newvertices)
10450 unsigned char *base;
10452 if (rsurface.array_size >= newvertices)
10454 if (rsurface.array_base)
10455 Mem_Free(rsurface.array_base);
10456 rsurface.array_size = (newvertices + 1023) & ~1023;
10458 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10459 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10460 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10461 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10462 size += rsurface.array_size * sizeof(float[3]);
10463 size += rsurface.array_size * sizeof(float[3]);
10464 size += rsurface.array_size * sizeof(float[3]);
10465 size += rsurface.array_size * sizeof(float[3]);
10466 size += rsurface.array_size * sizeof(float[3]);
10467 size += rsurface.array_size * sizeof(float[3]);
10468 size += rsurface.array_size * sizeof(float[3]);
10469 size += rsurface.array_size * sizeof(float[3]);
10470 size += rsurface.array_size * sizeof(float[4]);
10471 size += rsurface.array_size * sizeof(float[2]);
10472 size += rsurface.array_size * sizeof(float[2]);
10473 size += rsurface.array_size * sizeof(float[4]);
10474 size += rsurface.array_size * sizeof(int[3]);
10475 size += rsurface.array_size * sizeof(unsigned short[3]);
10476 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10477 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10478 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10479 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10480 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10481 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10482 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10483 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10484 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10485 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10486 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10487 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10488 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10489 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10490 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10491 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10492 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10493 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10494 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10497 void RSurf_ActiveWorldEntity(void)
10499 dp_model_t *model = r_refdef.scene.worldmodel;
10500 //if (rsurface.entity == r_refdef.scene.worldentity)
10502 rsurface.entity = r_refdef.scene.worldentity;
10503 rsurface.skeleton = NULL;
10504 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10505 rsurface.ent_skinnum = 0;
10506 rsurface.ent_qwskin = -1;
10507 rsurface.ent_shadertime = 0;
10508 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10509 if (rsurface.array_size < model->surfmesh.num_vertices)
10510 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10511 rsurface.matrix = identitymatrix;
10512 rsurface.inversematrix = identitymatrix;
10513 rsurface.matrixscale = 1;
10514 rsurface.inversematrixscale = 1;
10515 R_EntityMatrix(&identitymatrix);
10516 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10517 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10518 rsurface.fograngerecip = r_refdef.fograngerecip;
10519 rsurface.fogheightfade = r_refdef.fogheightfade;
10520 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10521 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10522 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10523 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10524 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10525 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10526 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10527 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10528 rsurface.colormod[3] = 1;
10529 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);
10530 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10531 rsurface.frameblend[0].lerp = 1;
10532 rsurface.ent_alttextures = false;
10533 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10534 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10535 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10536 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10537 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10538 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10539 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10540 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10541 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10542 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10543 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10544 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10545 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10546 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10547 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10548 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10549 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10550 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10551 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10552 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10553 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10554 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10555 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10556 rsurface.modelelement3i = model->surfmesh.data_element3i;
10557 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10558 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10559 rsurface.modelelement3s = model->surfmesh.data_element3s;
10560 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10561 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10562 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10563 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10564 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10565 rsurface.modelsurfaces = model->data_surfaces;
10566 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10567 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10568 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10569 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10570 rsurface.modelgeneratedvertex = false;
10571 rsurface.batchgeneratedvertex = false;
10572 rsurface.batchfirstvertex = 0;
10573 rsurface.batchnumvertices = 0;
10574 rsurface.batchfirsttriangle = 0;
10575 rsurface.batchnumtriangles = 0;
10576 rsurface.batchvertex3f = NULL;
10577 rsurface.batchvertex3f_vertexbuffer = NULL;
10578 rsurface.batchvertex3f_bufferoffset = 0;
10579 rsurface.batchsvector3f = NULL;
10580 rsurface.batchsvector3f_vertexbuffer = NULL;
10581 rsurface.batchsvector3f_bufferoffset = 0;
10582 rsurface.batchtvector3f = NULL;
10583 rsurface.batchtvector3f_vertexbuffer = NULL;
10584 rsurface.batchtvector3f_bufferoffset = 0;
10585 rsurface.batchnormal3f = NULL;
10586 rsurface.batchnormal3f_vertexbuffer = NULL;
10587 rsurface.batchnormal3f_bufferoffset = 0;
10588 rsurface.batchlightmapcolor4f = NULL;
10589 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10590 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10591 rsurface.batchtexcoordtexture2f = NULL;
10592 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10593 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10594 rsurface.batchtexcoordlightmap2f = NULL;
10595 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10596 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10597 rsurface.batchvertexmesh = NULL;
10598 rsurface.batchvertexmeshbuffer = NULL;
10599 rsurface.batchvertexposition = NULL;
10600 rsurface.batchvertexpositionbuffer = NULL;
10601 rsurface.batchelement3i = NULL;
10602 rsurface.batchelement3i_indexbuffer = NULL;
10603 rsurface.batchelement3i_bufferoffset = 0;
10604 rsurface.batchelement3s = NULL;
10605 rsurface.batchelement3s_indexbuffer = NULL;
10606 rsurface.batchelement3s_bufferoffset = 0;
10607 rsurface.passcolor4f = NULL;
10608 rsurface.passcolor4f_vertexbuffer = NULL;
10609 rsurface.passcolor4f_bufferoffset = 0;
10612 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10614 dp_model_t *model = ent->model;
10615 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10617 rsurface.entity = (entity_render_t *)ent;
10618 rsurface.skeleton = ent->skeleton;
10619 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10620 rsurface.ent_skinnum = ent->skinnum;
10621 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;
10622 rsurface.ent_shadertime = ent->shadertime;
10623 rsurface.ent_flags = ent->flags;
10624 if (rsurface.array_size < model->surfmesh.num_vertices)
10625 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10626 rsurface.matrix = ent->matrix;
10627 rsurface.inversematrix = ent->inversematrix;
10628 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10629 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10630 R_EntityMatrix(&rsurface.matrix);
10631 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10632 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10633 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10634 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10635 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10636 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10637 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10638 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10639 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10640 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10641 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10642 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10643 rsurface.colormod[3] = ent->alpha;
10644 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10645 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10646 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10647 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10648 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10649 if (ent->model->brush.submodel && !prepass)
10651 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10652 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10654 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10656 if (ent->animcache_vertex3f && !r_framedata_failed)
10658 rsurface.modelvertex3f = ent->animcache_vertex3f;
10659 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10660 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10661 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10662 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10663 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10664 rsurface.modelvertexposition = ent->animcache_vertexposition;
10665 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10667 else if (wanttangents)
10669 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10670 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10671 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10672 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10673 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10674 rsurface.modelvertexmesh = NULL;
10675 rsurface.modelvertexmeshbuffer = NULL;
10676 rsurface.modelvertexposition = NULL;
10677 rsurface.modelvertexpositionbuffer = NULL;
10679 else if (wantnormals)
10681 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10682 rsurface.modelsvector3f = NULL;
10683 rsurface.modeltvector3f = NULL;
10684 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10685 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10686 rsurface.modelvertexmesh = NULL;
10687 rsurface.modelvertexmeshbuffer = NULL;
10688 rsurface.modelvertexposition = NULL;
10689 rsurface.modelvertexpositionbuffer = NULL;
10693 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10694 rsurface.modelsvector3f = NULL;
10695 rsurface.modeltvector3f = NULL;
10696 rsurface.modelnormal3f = NULL;
10697 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10698 rsurface.modelvertexmesh = NULL;
10699 rsurface.modelvertexmeshbuffer = NULL;
10700 rsurface.modelvertexposition = NULL;
10701 rsurface.modelvertexpositionbuffer = NULL;
10703 rsurface.modelvertex3f_vertexbuffer = 0;
10704 rsurface.modelvertex3f_bufferoffset = 0;
10705 rsurface.modelsvector3f_vertexbuffer = 0;
10706 rsurface.modelsvector3f_bufferoffset = 0;
10707 rsurface.modeltvector3f_vertexbuffer = 0;
10708 rsurface.modeltvector3f_bufferoffset = 0;
10709 rsurface.modelnormal3f_vertexbuffer = 0;
10710 rsurface.modelnormal3f_bufferoffset = 0;
10711 rsurface.modelgeneratedvertex = true;
10715 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10716 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10717 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10718 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10719 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10720 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10721 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10722 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10723 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10724 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10725 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10726 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10727 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10728 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10729 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10730 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10731 rsurface.modelgeneratedvertex = false;
10733 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10734 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10735 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10736 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10737 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10738 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10739 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10740 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10741 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10742 rsurface.modelelement3i = model->surfmesh.data_element3i;
10743 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10744 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10745 rsurface.modelelement3s = model->surfmesh.data_element3s;
10746 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10747 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10748 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10749 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10750 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10751 rsurface.modelsurfaces = model->data_surfaces;
10752 rsurface.batchgeneratedvertex = false;
10753 rsurface.batchfirstvertex = 0;
10754 rsurface.batchnumvertices = 0;
10755 rsurface.batchfirsttriangle = 0;
10756 rsurface.batchnumtriangles = 0;
10757 rsurface.batchvertex3f = NULL;
10758 rsurface.batchvertex3f_vertexbuffer = NULL;
10759 rsurface.batchvertex3f_bufferoffset = 0;
10760 rsurface.batchsvector3f = NULL;
10761 rsurface.batchsvector3f_vertexbuffer = NULL;
10762 rsurface.batchsvector3f_bufferoffset = 0;
10763 rsurface.batchtvector3f = NULL;
10764 rsurface.batchtvector3f_vertexbuffer = NULL;
10765 rsurface.batchtvector3f_bufferoffset = 0;
10766 rsurface.batchnormal3f = NULL;
10767 rsurface.batchnormal3f_vertexbuffer = NULL;
10768 rsurface.batchnormal3f_bufferoffset = 0;
10769 rsurface.batchlightmapcolor4f = NULL;
10770 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10771 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10772 rsurface.batchtexcoordtexture2f = NULL;
10773 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10774 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10775 rsurface.batchtexcoordlightmap2f = NULL;
10776 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10777 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10778 rsurface.batchvertexmesh = NULL;
10779 rsurface.batchvertexmeshbuffer = NULL;
10780 rsurface.batchvertexposition = NULL;
10781 rsurface.batchvertexpositionbuffer = NULL;
10782 rsurface.batchelement3i = NULL;
10783 rsurface.batchelement3i_indexbuffer = NULL;
10784 rsurface.batchelement3i_bufferoffset = 0;
10785 rsurface.batchelement3s = NULL;
10786 rsurface.batchelement3s_indexbuffer = NULL;
10787 rsurface.batchelement3s_bufferoffset = 0;
10788 rsurface.passcolor4f = NULL;
10789 rsurface.passcolor4f_vertexbuffer = NULL;
10790 rsurface.passcolor4f_bufferoffset = 0;
10793 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)
10797 rsurface.entity = r_refdef.scene.worldentity;
10798 rsurface.skeleton = NULL;
10799 rsurface.ent_skinnum = 0;
10800 rsurface.ent_qwskin = -1;
10801 rsurface.ent_shadertime = shadertime;
10802 rsurface.ent_flags = entflags;
10803 rsurface.modelnumvertices = numvertices;
10804 rsurface.modelnumtriangles = numtriangles;
10805 if (rsurface.array_size < rsurface.modelnumvertices)
10806 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10807 rsurface.matrix = *matrix;
10808 rsurface.inversematrix = *inversematrix;
10809 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10810 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10811 R_EntityMatrix(&rsurface.matrix);
10812 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10813 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10814 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10815 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10816 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10817 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10818 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10819 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10820 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10821 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10822 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10823 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10824 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);
10825 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10826 rsurface.frameblend[0].lerp = 1;
10827 rsurface.ent_alttextures = false;
10828 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10829 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10832 rsurface.modelvertex3f = vertex3f;
10833 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10834 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10835 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10837 else if (wantnormals)
10839 rsurface.modelvertex3f = vertex3f;
10840 rsurface.modelsvector3f = NULL;
10841 rsurface.modeltvector3f = NULL;
10842 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10846 rsurface.modelvertex3f = vertex3f;
10847 rsurface.modelsvector3f = NULL;
10848 rsurface.modeltvector3f = NULL;
10849 rsurface.modelnormal3f = NULL;
10851 rsurface.modelvertexmesh = NULL;
10852 rsurface.modelvertexmeshbuffer = NULL;
10853 rsurface.modelvertexposition = NULL;
10854 rsurface.modelvertexpositionbuffer = NULL;
10855 rsurface.modelvertex3f_vertexbuffer = 0;
10856 rsurface.modelvertex3f_bufferoffset = 0;
10857 rsurface.modelsvector3f_vertexbuffer = 0;
10858 rsurface.modelsvector3f_bufferoffset = 0;
10859 rsurface.modeltvector3f_vertexbuffer = 0;
10860 rsurface.modeltvector3f_bufferoffset = 0;
10861 rsurface.modelnormal3f_vertexbuffer = 0;
10862 rsurface.modelnormal3f_bufferoffset = 0;
10863 rsurface.modelgeneratedvertex = true;
10864 rsurface.modellightmapcolor4f = color4f;
10865 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10866 rsurface.modellightmapcolor4f_bufferoffset = 0;
10867 rsurface.modeltexcoordtexture2f = texcoord2f;
10868 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10869 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10870 rsurface.modeltexcoordlightmap2f = NULL;
10871 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10872 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10873 rsurface.modelelement3i = element3i;
10874 rsurface.modelelement3i_indexbuffer = NULL;
10875 rsurface.modelelement3i_bufferoffset = 0;
10876 rsurface.modelelement3s = element3s;
10877 rsurface.modelelement3s_indexbuffer = NULL;
10878 rsurface.modelelement3s_bufferoffset = 0;
10879 rsurface.modellightmapoffsets = NULL;
10880 rsurface.modelsurfaces = NULL;
10881 rsurface.batchgeneratedvertex = false;
10882 rsurface.batchfirstvertex = 0;
10883 rsurface.batchnumvertices = 0;
10884 rsurface.batchfirsttriangle = 0;
10885 rsurface.batchnumtriangles = 0;
10886 rsurface.batchvertex3f = NULL;
10887 rsurface.batchvertex3f_vertexbuffer = NULL;
10888 rsurface.batchvertex3f_bufferoffset = 0;
10889 rsurface.batchsvector3f = NULL;
10890 rsurface.batchsvector3f_vertexbuffer = NULL;
10891 rsurface.batchsvector3f_bufferoffset = 0;
10892 rsurface.batchtvector3f = NULL;
10893 rsurface.batchtvector3f_vertexbuffer = NULL;
10894 rsurface.batchtvector3f_bufferoffset = 0;
10895 rsurface.batchnormal3f = NULL;
10896 rsurface.batchnormal3f_vertexbuffer = NULL;
10897 rsurface.batchnormal3f_bufferoffset = 0;
10898 rsurface.batchlightmapcolor4f = NULL;
10899 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10900 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10901 rsurface.batchtexcoordtexture2f = NULL;
10902 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10903 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10904 rsurface.batchtexcoordlightmap2f = NULL;
10905 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10906 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10907 rsurface.batchvertexmesh = NULL;
10908 rsurface.batchvertexmeshbuffer = NULL;
10909 rsurface.batchvertexposition = NULL;
10910 rsurface.batchvertexpositionbuffer = NULL;
10911 rsurface.batchelement3i = NULL;
10912 rsurface.batchelement3i_indexbuffer = NULL;
10913 rsurface.batchelement3i_bufferoffset = 0;
10914 rsurface.batchelement3s = NULL;
10915 rsurface.batchelement3s_indexbuffer = NULL;
10916 rsurface.batchelement3s_bufferoffset = 0;
10917 rsurface.passcolor4f = NULL;
10918 rsurface.passcolor4f_vertexbuffer = NULL;
10919 rsurface.passcolor4f_bufferoffset = 0;
10921 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10923 if ((wantnormals || wanttangents) && !normal3f)
10925 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10926 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10928 if (wanttangents && !svector3f)
10930 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);
10931 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10932 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10936 // now convert arrays into vertexmesh structs
10937 for (i = 0;i < numvertices;i++)
10939 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10940 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10941 if (rsurface.modelsvector3f)
10942 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10943 if (rsurface.modeltvector3f)
10944 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10945 if (rsurface.modelnormal3f)
10946 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10947 if (rsurface.modellightmapcolor4f)
10948 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10949 if (rsurface.modeltexcoordtexture2f)
10950 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10951 if (rsurface.modeltexcoordlightmap2f)
10952 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10956 float RSurf_FogPoint(const float *v)
10958 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10959 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10960 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10961 float FogHeightFade = r_refdef.fogheightfade;
10963 unsigned int fogmasktableindex;
10964 if (r_refdef.fogplaneviewabove)
10965 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10967 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10968 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10969 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10972 float RSurf_FogVertex(const float *v)
10974 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10975 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10976 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10977 float FogHeightFade = rsurface.fogheightfade;
10979 unsigned int fogmasktableindex;
10980 if (r_refdef.fogplaneviewabove)
10981 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10983 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10984 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10985 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10988 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10991 for (i = 0;i < numelements;i++)
10992 outelement3i[i] = inelement3i[i] + adjust;
10995 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10996 extern cvar_t gl_vbo;
10997 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11005 int surfacefirsttriangle;
11006 int surfacenumtriangles;
11007 int surfacefirstvertex;
11008 int surfaceendvertex;
11009 int surfacenumvertices;
11010 int surfaceadjustvertex;
11014 qboolean dynamicvertex;
11018 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11019 float waveparms[4];
11020 q3shaderinfo_deform_t *deform;
11021 const msurface_t *surface, *firstsurface;
11022 r_vertexposition_t *vertexposition;
11023 r_vertexmesh_t *vertexmesh;
11024 if (!texturenumsurfaces)
11026 // find vertex range of this surface batch
11028 firstsurface = texturesurfacelist[0];
11029 firsttriangle = firstsurface->num_firsttriangle;
11031 firstvertex = endvertex = firstsurface->num_firstvertex;
11032 for (i = 0;i < texturenumsurfaces;i++)
11034 surface = texturesurfacelist[i];
11035 if (surface != firstsurface + i)
11037 surfacefirstvertex = surface->num_firstvertex;
11038 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11039 surfacenumtriangles = surface->num_triangles;
11040 if (firstvertex > surfacefirstvertex)
11041 firstvertex = surfacefirstvertex;
11042 if (endvertex < surfaceendvertex)
11043 endvertex = surfaceendvertex;
11044 numtriangles += surfacenumtriangles;
11049 // we now know the vertex range used, and if there are any gaps in it
11050 rsurface.batchfirstvertex = firstvertex;
11051 rsurface.batchnumvertices = endvertex - firstvertex;
11052 rsurface.batchfirsttriangle = firsttriangle;
11053 rsurface.batchnumtriangles = numtriangles;
11055 // this variable holds flags for which properties have been updated that
11056 // may require regenerating vertexmesh or vertexposition arrays...
11059 // check if any dynamic vertex processing must occur
11060 dynamicvertex = false;
11062 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11063 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11064 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11066 switch (deform->deform)
11069 case Q3DEFORM_PROJECTIONSHADOW:
11070 case Q3DEFORM_TEXT0:
11071 case Q3DEFORM_TEXT1:
11072 case Q3DEFORM_TEXT2:
11073 case Q3DEFORM_TEXT3:
11074 case Q3DEFORM_TEXT4:
11075 case Q3DEFORM_TEXT5:
11076 case Q3DEFORM_TEXT6:
11077 case Q3DEFORM_TEXT7:
11078 case Q3DEFORM_NONE:
11080 case Q3DEFORM_AUTOSPRITE:
11081 dynamicvertex = true;
11082 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11083 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11085 case Q3DEFORM_AUTOSPRITE2:
11086 dynamicvertex = true;
11087 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11088 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11090 case Q3DEFORM_NORMAL:
11091 dynamicvertex = true;
11092 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11093 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11095 case Q3DEFORM_WAVE:
11096 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11097 break; // if wavefunc is a nop, ignore this transform
11098 dynamicvertex = true;
11099 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11100 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11102 case Q3DEFORM_BULGE:
11103 dynamicvertex = true;
11104 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11105 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11107 case Q3DEFORM_MOVE:
11108 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11109 break; // if wavefunc is a nop, ignore this transform
11110 dynamicvertex = true;
11111 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11112 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11116 switch(rsurface.texture->tcgen.tcgen)
11119 case Q3TCGEN_TEXTURE:
11121 case Q3TCGEN_LIGHTMAP:
11122 dynamicvertex = true;
11123 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11124 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11126 case Q3TCGEN_VECTOR:
11127 dynamicvertex = true;
11128 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11129 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11131 case Q3TCGEN_ENVIRONMENT:
11132 dynamicvertex = true;
11133 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11134 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11137 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11139 dynamicvertex = true;
11140 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11141 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11144 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11146 dynamicvertex = true;
11147 batchneed |= BATCHNEED_NOGAPS;
11148 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11151 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11153 dynamicvertex = true;
11154 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11155 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11158 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11160 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11161 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11162 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11163 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11164 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11165 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11166 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11169 // when the model data has no vertex buffer (dynamic mesh), we need to
11171 if (!rsurface.modelvertexmeshbuffer)
11172 batchneed |= BATCHNEED_NOGAPS;
11174 // if needsupdate, we have to do a dynamic vertex batch for sure
11175 if (needsupdate & batchneed)
11176 dynamicvertex = true;
11178 // see if we need to build vertexmesh from arrays
11179 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11180 dynamicvertex = true;
11182 // see if we need to build vertexposition from arrays
11183 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11184 dynamicvertex = true;
11186 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11187 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11188 dynamicvertex = true;
11190 // if there is a chance of animated vertex colors, it's a dynamic batch
11191 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11192 dynamicvertex = true;
11194 rsurface.batchvertex3f = rsurface.modelvertex3f;
11195 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11196 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11197 rsurface.batchsvector3f = rsurface.modelsvector3f;
11198 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11199 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11200 rsurface.batchtvector3f = rsurface.modeltvector3f;
11201 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11202 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11203 rsurface.batchnormal3f = rsurface.modelnormal3f;
11204 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11205 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11206 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11207 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11208 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11209 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11210 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11211 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11212 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11213 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11214 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11215 rsurface.batchvertexposition = rsurface.modelvertexposition;
11216 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11217 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11218 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11219 rsurface.batchelement3i = rsurface.modelelement3i;
11220 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11221 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11222 rsurface.batchelement3s = rsurface.modelelement3s;
11223 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11224 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11226 // if any dynamic vertex processing has to occur in software, we copy the
11227 // entire surface list together before processing to rebase the vertices
11228 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11230 // if any gaps exist and we do not have a static vertex buffer, we have to
11231 // copy the surface list together to avoid wasting upload bandwidth on the
11232 // vertices in the gaps.
11234 // if gaps exist and we have a static vertex buffer, we still have to
11235 // combine the index buffer ranges into one dynamic index buffer.
11237 // in all cases we end up with data that can be drawn in one call.
11239 if (!dynamicvertex)
11241 // static vertex data, just set pointers...
11242 rsurface.batchgeneratedvertex = false;
11243 // if there are gaps, we want to build a combined index buffer,
11244 // otherwise use the original static buffer with an appropriate offset
11249 for (i = 0;i < texturenumsurfaces;i++)
11251 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11252 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11253 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11254 numtriangles += surfacenumtriangles;
11256 rsurface.batchelement3i = rsurface.array_batchelement3i;
11257 rsurface.batchelement3i_indexbuffer = NULL;
11258 rsurface.batchelement3i_bufferoffset = 0;
11259 rsurface.batchelement3s = NULL;
11260 rsurface.batchelement3s_indexbuffer = NULL;
11261 rsurface.batchelement3s_bufferoffset = 0;
11262 if (endvertex <= 65536)
11264 rsurface.batchelement3s = rsurface.array_batchelement3s;
11265 for (i = 0;i < numtriangles*3;i++)
11266 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11268 rsurface.batchfirsttriangle = firsttriangle;
11269 rsurface.batchnumtriangles = numtriangles;
11274 // something needs software processing, do it for real...
11275 // we only directly handle interleaved array data in this case...
11276 rsurface.batchgeneratedvertex = true;
11278 // now copy the vertex data into a combined array and make an index array
11279 // (this is what Quake3 does all the time)
11280 //if (gaps || rsurface.batchfirstvertex)
11282 rsurface.batchvertexposition = NULL;
11283 rsurface.batchvertexpositionbuffer = NULL;
11284 rsurface.batchvertexmesh = NULL;
11285 rsurface.batchvertexmeshbuffer = NULL;
11286 rsurface.batchvertex3f = NULL;
11287 rsurface.batchvertex3f_vertexbuffer = NULL;
11288 rsurface.batchvertex3f_bufferoffset = 0;
11289 rsurface.batchsvector3f = NULL;
11290 rsurface.batchsvector3f_vertexbuffer = NULL;
11291 rsurface.batchsvector3f_bufferoffset = 0;
11292 rsurface.batchtvector3f = NULL;
11293 rsurface.batchtvector3f_vertexbuffer = NULL;
11294 rsurface.batchtvector3f_bufferoffset = 0;
11295 rsurface.batchnormal3f = NULL;
11296 rsurface.batchnormal3f_vertexbuffer = NULL;
11297 rsurface.batchnormal3f_bufferoffset = 0;
11298 rsurface.batchlightmapcolor4f = NULL;
11299 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11300 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11301 rsurface.batchtexcoordtexture2f = NULL;
11302 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11303 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11304 rsurface.batchtexcoordlightmap2f = NULL;
11305 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11306 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11307 rsurface.batchelement3i = rsurface.array_batchelement3i;
11308 rsurface.batchelement3i_indexbuffer = NULL;
11309 rsurface.batchelement3i_bufferoffset = 0;
11310 rsurface.batchelement3s = NULL;
11311 rsurface.batchelement3s_indexbuffer = NULL;
11312 rsurface.batchelement3s_bufferoffset = 0;
11313 // we'll only be setting up certain arrays as needed
11314 if (batchneed & BATCHNEED_VERTEXPOSITION)
11315 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11316 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11317 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11318 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11319 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11320 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11321 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11322 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11324 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11325 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11327 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11328 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11329 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11330 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11331 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11332 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11335 for (i = 0;i < texturenumsurfaces;i++)
11337 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11338 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11339 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11340 surfaceadjustvertex = numvertices - surfacefirstvertex;
11341 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11342 // copy only the data requested
11343 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11344 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11345 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11346 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11347 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11349 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11350 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11351 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11352 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11353 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11355 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11356 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11358 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11359 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11360 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11361 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11362 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11363 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11365 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11366 numvertices += surfacenumvertices;
11367 numtriangles += surfacenumtriangles;
11370 // generate a 16bit index array as well if possible
11371 // (in general, dynamic batches fit)
11372 if (numvertices <= 65536)
11374 rsurface.batchelement3s = rsurface.array_batchelement3s;
11375 for (i = 0;i < numtriangles*3;i++)
11376 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11379 // since we've copied everything, the batch now starts at 0
11380 rsurface.batchfirstvertex = 0;
11381 rsurface.batchnumvertices = numvertices;
11382 rsurface.batchfirsttriangle = 0;
11383 rsurface.batchnumtriangles = numtriangles;
11386 // q1bsp surfaces rendered in vertex color mode have to have colors
11387 // calculated based on lightstyles
11388 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11390 // generate color arrays for the surfaces in this list
11394 const int *offsets;
11395 const unsigned char *lm;
11397 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11398 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11399 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11400 for (i = 0;i < texturenumsurfaces;i++)
11402 surface = texturesurfacelist[i];
11403 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11404 surfacenumvertices = surface->num_vertices;
11405 if (surface->lightmapinfo->samples)
11407 for (j = 0;j < surfacenumvertices;j++)
11409 lm = surface->lightmapinfo->samples + offsets[j];
11410 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11411 VectorScale(lm, scale, c);
11412 if (surface->lightmapinfo->styles[1] != 255)
11414 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11416 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11417 VectorMA(c, scale, lm, c);
11418 if (surface->lightmapinfo->styles[2] != 255)
11421 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11422 VectorMA(c, scale, lm, c);
11423 if (surface->lightmapinfo->styles[3] != 255)
11426 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11427 VectorMA(c, scale, lm, c);
11434 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);
11440 for (j = 0;j < surfacenumvertices;j++)
11442 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11449 // if vertices are deformed (sprite flares and things in maps, possibly
11450 // water waves, bulges and other deformations), modify the copied vertices
11452 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11454 switch (deform->deform)
11457 case Q3DEFORM_PROJECTIONSHADOW:
11458 case Q3DEFORM_TEXT0:
11459 case Q3DEFORM_TEXT1:
11460 case Q3DEFORM_TEXT2:
11461 case Q3DEFORM_TEXT3:
11462 case Q3DEFORM_TEXT4:
11463 case Q3DEFORM_TEXT5:
11464 case Q3DEFORM_TEXT6:
11465 case Q3DEFORM_TEXT7:
11466 case Q3DEFORM_NONE:
11468 case Q3DEFORM_AUTOSPRITE:
11469 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11470 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11471 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11472 VectorNormalize(newforward);
11473 VectorNormalize(newright);
11474 VectorNormalize(newup);
11475 // a single autosprite surface can contain multiple sprites...
11476 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11478 VectorClear(center);
11479 for (i = 0;i < 4;i++)
11480 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11481 VectorScale(center, 0.25f, center);
11482 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11483 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11484 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11485 for (i = 0;i < 4;i++)
11487 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11488 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11491 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11492 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11493 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);
11494 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11495 rsurface.batchvertex3f_vertexbuffer = NULL;
11496 rsurface.batchvertex3f_bufferoffset = 0;
11497 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11498 rsurface.batchsvector3f_vertexbuffer = NULL;
11499 rsurface.batchsvector3f_bufferoffset = 0;
11500 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11501 rsurface.batchtvector3f_vertexbuffer = NULL;
11502 rsurface.batchtvector3f_bufferoffset = 0;
11503 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11504 rsurface.batchnormal3f_vertexbuffer = NULL;
11505 rsurface.batchnormal3f_bufferoffset = 0;
11507 case Q3DEFORM_AUTOSPRITE2:
11508 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11509 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11510 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11511 VectorNormalize(newforward);
11512 VectorNormalize(newright);
11513 VectorNormalize(newup);
11515 const float *v1, *v2;
11525 memset(shortest, 0, sizeof(shortest));
11526 // a single autosprite surface can contain multiple sprites...
11527 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11529 VectorClear(center);
11530 for (i = 0;i < 4;i++)
11531 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11532 VectorScale(center, 0.25f, center);
11533 // find the two shortest edges, then use them to define the
11534 // axis vectors for rotating around the central axis
11535 for (i = 0;i < 6;i++)
11537 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11538 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11539 l = VectorDistance2(v1, v2);
11540 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11541 if (v1[2] != v2[2])
11542 l += (1.0f / 1024.0f);
11543 if (shortest[0].length2 > l || i == 0)
11545 shortest[1] = shortest[0];
11546 shortest[0].length2 = l;
11547 shortest[0].v1 = v1;
11548 shortest[0].v2 = v2;
11550 else if (shortest[1].length2 > l || i == 1)
11552 shortest[1].length2 = l;
11553 shortest[1].v1 = v1;
11554 shortest[1].v2 = v2;
11557 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11558 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11559 // this calculates the right vector from the shortest edge
11560 // and the up vector from the edge midpoints
11561 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11562 VectorNormalize(right);
11563 VectorSubtract(end, start, up);
11564 VectorNormalize(up);
11565 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11566 VectorSubtract(rsurface.localvieworigin, center, forward);
11567 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11568 VectorNegate(forward, forward);
11569 VectorReflect(forward, 0, up, forward);
11570 VectorNormalize(forward);
11571 CrossProduct(up, forward, newright);
11572 VectorNormalize(newright);
11573 // rotate the quad around the up axis vector, this is made
11574 // especially easy by the fact we know the quad is flat,
11575 // so we only have to subtract the center position and
11576 // measure distance along the right vector, and then
11577 // multiply that by the newright vector and add back the
11579 // we also need to subtract the old position to undo the
11580 // displacement from the center, which we do with a
11581 // DotProduct, the subtraction/addition of center is also
11582 // optimized into DotProducts here
11583 l = DotProduct(right, center);
11584 for (i = 0;i < 4;i++)
11586 v1 = rsurface.batchvertex3f + 3*(j+i);
11587 f = DotProduct(right, v1) - l;
11588 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11592 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11593 rsurface.batchvertex3f_vertexbuffer = NULL;
11594 rsurface.batchvertex3f_bufferoffset = 0;
11595 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11597 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11598 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11599 rsurface.batchnormal3f_vertexbuffer = NULL;
11600 rsurface.batchnormal3f_bufferoffset = 0;
11602 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11604 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);
11605 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11606 rsurface.batchsvector3f_vertexbuffer = NULL;
11607 rsurface.batchsvector3f_bufferoffset = 0;
11608 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11609 rsurface.batchtvector3f_vertexbuffer = NULL;
11610 rsurface.batchtvector3f_bufferoffset = 0;
11613 case Q3DEFORM_NORMAL:
11614 // deform the normals to make reflections wavey
11615 for (j = 0;j < rsurface.batchnumvertices;j++)
11618 float *normal = rsurface.array_batchnormal3f + 3*j;
11619 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11620 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11621 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]);
11622 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]);
11623 VectorNormalize(normal);
11625 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11626 rsurface.batchnormal3f_vertexbuffer = NULL;
11627 rsurface.batchnormal3f_bufferoffset = 0;
11628 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11630 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);
11631 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11632 rsurface.batchsvector3f_vertexbuffer = NULL;
11633 rsurface.batchsvector3f_bufferoffset = 0;
11634 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11635 rsurface.batchtvector3f_vertexbuffer = NULL;
11636 rsurface.batchtvector3f_bufferoffset = 0;
11639 case Q3DEFORM_WAVE:
11640 // deform vertex array to make wavey water and flags and such
11641 waveparms[0] = deform->waveparms[0];
11642 waveparms[1] = deform->waveparms[1];
11643 waveparms[2] = deform->waveparms[2];
11644 waveparms[3] = deform->waveparms[3];
11645 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11646 break; // if wavefunc is a nop, don't make a dynamic vertex array
11647 // this is how a divisor of vertex influence on deformation
11648 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11649 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11650 for (j = 0;j < rsurface.batchnumvertices;j++)
11652 // if the wavefunc depends on time, evaluate it per-vertex
11655 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11656 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11658 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11660 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11661 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11662 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11663 rsurface.batchvertex3f_vertexbuffer = NULL;
11664 rsurface.batchvertex3f_bufferoffset = 0;
11665 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11666 rsurface.batchnormal3f_vertexbuffer = NULL;
11667 rsurface.batchnormal3f_bufferoffset = 0;
11668 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11670 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);
11671 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11672 rsurface.batchsvector3f_vertexbuffer = NULL;
11673 rsurface.batchsvector3f_bufferoffset = 0;
11674 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11675 rsurface.batchtvector3f_vertexbuffer = NULL;
11676 rsurface.batchtvector3f_bufferoffset = 0;
11679 case Q3DEFORM_BULGE:
11680 // deform vertex array to make the surface have moving bulges
11681 for (j = 0;j < rsurface.batchnumvertices;j++)
11683 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11684 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11686 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11687 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11688 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11689 rsurface.batchvertex3f_vertexbuffer = NULL;
11690 rsurface.batchvertex3f_bufferoffset = 0;
11691 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11692 rsurface.batchnormal3f_vertexbuffer = NULL;
11693 rsurface.batchnormal3f_bufferoffset = 0;
11694 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11696 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);
11697 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11698 rsurface.batchsvector3f_vertexbuffer = NULL;
11699 rsurface.batchsvector3f_bufferoffset = 0;
11700 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11701 rsurface.batchtvector3f_vertexbuffer = NULL;
11702 rsurface.batchtvector3f_bufferoffset = 0;
11705 case Q3DEFORM_MOVE:
11706 // deform vertex array
11707 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11708 break; // if wavefunc is a nop, don't make a dynamic vertex array
11709 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11710 VectorScale(deform->parms, scale, waveparms);
11711 for (j = 0;j < rsurface.batchnumvertices;j++)
11712 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11713 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11714 rsurface.batchvertex3f_vertexbuffer = NULL;
11715 rsurface.batchvertex3f_bufferoffset = 0;
11720 // generate texcoords based on the chosen texcoord source
11721 switch(rsurface.texture->tcgen.tcgen)
11724 case Q3TCGEN_TEXTURE:
11726 case Q3TCGEN_LIGHTMAP:
11727 if (rsurface.batchtexcoordlightmap2f)
11728 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11729 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11730 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11731 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11733 case Q3TCGEN_VECTOR:
11734 for (j = 0;j < rsurface.batchnumvertices;j++)
11736 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11737 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11739 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11740 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11741 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11743 case Q3TCGEN_ENVIRONMENT:
11744 // make environment reflections using a spheremap
11745 for (j = 0;j < rsurface.batchnumvertices;j++)
11747 // identical to Q3A's method, but executed in worldspace so
11748 // carried models can be shiny too
11750 float viewer[3], d, reflected[3], worldreflected[3];
11752 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11753 // VectorNormalize(viewer);
11755 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11757 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11758 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11759 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11760 // note: this is proportinal to viewer, so we can normalize later
11762 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11763 VectorNormalize(worldreflected);
11765 // note: this sphere map only uses world x and z!
11766 // so positive and negative y will LOOK THE SAME.
11767 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11768 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11770 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11771 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11772 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11775 // the only tcmod that needs software vertex processing is turbulent, so
11776 // check for it here and apply the changes if needed
11777 // and we only support that as the first one
11778 // (handling a mixture of turbulent and other tcmods would be problematic
11779 // without punting it entirely to a software path)
11780 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11782 amplitude = rsurface.texture->tcmods[0].parms[1];
11783 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11784 for (j = 0;j < rsurface.batchnumvertices;j++)
11786 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);
11787 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11789 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11790 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11791 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11794 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11796 // convert the modified arrays to vertex structs
11797 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11798 rsurface.batchvertexmeshbuffer = NULL;
11799 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11800 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11801 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11802 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11803 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11804 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11805 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11807 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11809 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11810 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11813 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11814 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11815 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11816 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11817 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11818 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11819 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11820 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11821 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11824 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11826 // convert the modified arrays to vertex structs
11827 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11828 rsurface.batchvertexpositionbuffer = NULL;
11829 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11830 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11832 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11833 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11837 void RSurf_DrawBatch(void)
11839 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);
11842 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11844 // pick the closest matching water plane
11845 int planeindex, vertexindex, bestplaneindex = -1;
11849 r_waterstate_waterplane_t *p;
11851 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11853 if(p->camera_entity != rsurface.texture->camera_entity)
11856 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11857 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11859 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11860 d += fabs(PlaneDiff(vert, &p->plane));
11862 if (bestd > d || bestplaneindex < 0)
11865 bestplaneindex = planeindex;
11868 return bestplaneindex;
11871 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11874 for (i = 0;i < rsurface.batchnumvertices;i++)
11875 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11876 rsurface.passcolor4f = rsurface.array_passcolor4f;
11877 rsurface.passcolor4f_vertexbuffer = 0;
11878 rsurface.passcolor4f_bufferoffset = 0;
11881 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11888 if (rsurface.passcolor4f)
11890 // generate color arrays
11891 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)
11893 f = RSurf_FogVertex(v);
11902 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11904 f = RSurf_FogVertex(v);
11911 rsurface.passcolor4f = rsurface.array_passcolor4f;
11912 rsurface.passcolor4f_vertexbuffer = 0;
11913 rsurface.passcolor4f_bufferoffset = 0;
11916 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11923 if (!rsurface.passcolor4f)
11925 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)
11927 f = RSurf_FogVertex(v);
11928 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11929 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11930 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11933 rsurface.passcolor4f = rsurface.array_passcolor4f;
11934 rsurface.passcolor4f_vertexbuffer = 0;
11935 rsurface.passcolor4f_bufferoffset = 0;
11938 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11943 if (!rsurface.passcolor4f)
11945 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11952 rsurface.passcolor4f = rsurface.array_passcolor4f;
11953 rsurface.passcolor4f_vertexbuffer = 0;
11954 rsurface.passcolor4f_bufferoffset = 0;
11957 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11962 if (!rsurface.passcolor4f)
11964 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11966 c2[0] = c[0] + r_refdef.scene.ambient;
11967 c2[1] = c[1] + r_refdef.scene.ambient;
11968 c2[2] = c[2] + r_refdef.scene.ambient;
11971 rsurface.passcolor4f = rsurface.array_passcolor4f;
11972 rsurface.passcolor4f_vertexbuffer = 0;
11973 rsurface.passcolor4f_bufferoffset = 0;
11976 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11979 rsurface.passcolor4f = NULL;
11980 rsurface.passcolor4f_vertexbuffer = 0;
11981 rsurface.passcolor4f_bufferoffset = 0;
11982 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11983 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11984 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11985 GL_Color(r, g, b, a);
11986 R_Mesh_TexBind(0, rsurface.lightmaptexture);
11990 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11992 // TODO: optimize applyfog && applycolor case
11993 // just apply fog if necessary, and tint the fog color array if necessary
11994 rsurface.passcolor4f = NULL;
11995 rsurface.passcolor4f_vertexbuffer = 0;
11996 rsurface.passcolor4f_bufferoffset = 0;
11997 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11998 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11999 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12000 GL_Color(r, g, b, a);
12004 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12007 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12008 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12009 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12010 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12011 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12012 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12013 GL_Color(r, g, b, a);
12017 static void RSurf_DrawBatch_GL11_ClampColor(void)
12022 if (!rsurface.passcolor4f)
12024 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12026 c2[0] = bound(0.0f, c1[0], 1.0f);
12027 c2[1] = bound(0.0f, c1[1], 1.0f);
12028 c2[2] = bound(0.0f, c1[2], 1.0f);
12029 c2[3] = bound(0.0f, c1[3], 1.0f);
12033 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12041 vec3_t ambientcolor;
12042 vec3_t diffusecolor;
12046 VectorCopy(rsurface.modellight_lightdir, lightdir);
12047 f = 0.5f * r_refdef.lightmapintensity;
12048 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12049 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12050 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12051 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12052 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12053 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12055 if (VectorLength2(diffusecolor) > 0)
12057 // q3-style directional shading
12058 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)
12060 if ((f = DotProduct(n, lightdir)) > 0)
12061 VectorMA(ambientcolor, f, diffusecolor, c);
12063 VectorCopy(ambientcolor, c);
12070 rsurface.passcolor4f = rsurface.array_passcolor4f;
12071 rsurface.passcolor4f_vertexbuffer = 0;
12072 rsurface.passcolor4f_bufferoffset = 0;
12073 *applycolor = false;
12077 *r = ambientcolor[0];
12078 *g = ambientcolor[1];
12079 *b = ambientcolor[2];
12080 rsurface.passcolor4f = NULL;
12081 rsurface.passcolor4f_vertexbuffer = 0;
12082 rsurface.passcolor4f_bufferoffset = 0;
12086 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12088 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12089 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12090 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12091 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12092 GL_Color(r, g, b, a);
12096 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12102 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12104 f = 1 - RSurf_FogVertex(v);
12112 void RSurf_SetupDepthAndCulling(void)
12114 // submodels are biased to avoid z-fighting with world surfaces that they
12115 // may be exactly overlapping (avoids z-fighting artifacts on certain
12116 // doors and things in Quake maps)
12117 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12118 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12119 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12120 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12123 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12125 // transparent sky would be ridiculous
12126 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12128 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12129 skyrenderlater = true;
12130 RSurf_SetupDepthAndCulling();
12131 GL_DepthMask(true);
12132 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12133 // skymasking on them, and Quake3 never did sky masking (unlike
12134 // software Quake and software Quake2), so disable the sky masking
12135 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12136 // and skymasking also looks very bad when noclipping outside the
12137 // level, so don't use it then either.
12138 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12140 R_Mesh_ResetTextureState();
12141 if (skyrendermasked)
12143 R_SetupShader_DepthOrShadow();
12144 // depth-only (masking)
12145 GL_ColorMask(0,0,0,0);
12146 // just to make sure that braindead drivers don't draw
12147 // anything despite that colormask...
12148 GL_BlendFunc(GL_ZERO, GL_ONE);
12149 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12150 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12154 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12156 GL_BlendFunc(GL_ONE, GL_ZERO);
12157 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12158 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12159 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12162 if (skyrendermasked)
12163 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12165 R_Mesh_ResetTextureState();
12166 GL_Color(1, 1, 1, 1);
12169 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12170 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12171 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12173 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12177 // render screenspace normalmap to texture
12178 GL_DepthMask(true);
12179 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12184 // bind lightmap texture
12186 // water/refraction/reflection/camera surfaces have to be handled specially
12187 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12189 int start, end, startplaneindex;
12190 for (start = 0;start < texturenumsurfaces;start = end)
12192 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12193 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12195 // now that we have a batch using the same planeindex, render it
12196 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12198 // render water or distortion background
12199 GL_DepthMask(true);
12200 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));
12202 // blend surface on top
12203 GL_DepthMask(false);
12204 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12207 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12209 // render surface with reflection texture as input
12210 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12211 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));
12218 // render surface batch normally
12219 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12220 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12224 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12226 // OpenGL 1.3 path - anything not completely ancient
12227 qboolean applycolor;
12230 const texturelayer_t *layer;
12231 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);
12232 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12234 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12237 int layertexrgbscale;
12238 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12240 if (layerindex == 0)
12241 GL_AlphaTest(true);
12244 GL_AlphaTest(false);
12245 GL_DepthFunc(GL_EQUAL);
12248 GL_DepthMask(layer->depthmask && writedepth);
12249 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12250 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12252 layertexrgbscale = 4;
12253 VectorScale(layer->color, 0.25f, layercolor);
12255 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12257 layertexrgbscale = 2;
12258 VectorScale(layer->color, 0.5f, layercolor);
12262 layertexrgbscale = 1;
12263 VectorScale(layer->color, 1.0f, layercolor);
12265 layercolor[3] = layer->color[3];
12266 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12267 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12268 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12269 switch (layer->type)
12271 case TEXTURELAYERTYPE_LITTEXTURE:
12272 // single-pass lightmapped texture with 2x rgbscale
12273 R_Mesh_TexBind(0, r_texture_white);
12274 R_Mesh_TexMatrix(0, NULL);
12275 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12276 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12277 R_Mesh_TexBind(1, layer->texture);
12278 R_Mesh_TexMatrix(1, &layer->texmatrix);
12279 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12280 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12281 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12282 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12283 else if (rsurface.uselightmaptexture)
12284 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12286 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12288 case TEXTURELAYERTYPE_TEXTURE:
12289 // singletexture unlit texture with transparency support
12290 R_Mesh_TexBind(0, layer->texture);
12291 R_Mesh_TexMatrix(0, &layer->texmatrix);
12292 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12293 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12294 R_Mesh_TexBind(1, 0);
12295 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12296 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12298 case TEXTURELAYERTYPE_FOG:
12299 // singletexture fogging
12300 if (layer->texture)
12302 R_Mesh_TexBind(0, layer->texture);
12303 R_Mesh_TexMatrix(0, &layer->texmatrix);
12304 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12305 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12309 R_Mesh_TexBind(0, 0);
12310 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12312 R_Mesh_TexBind(1, 0);
12313 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12314 // generate a color array for the fog pass
12315 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12316 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12320 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12325 GL_DepthFunc(GL_LEQUAL);
12326 GL_AlphaTest(false);
12330 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12332 // OpenGL 1.1 - crusty old voodoo path
12335 const texturelayer_t *layer;
12336 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);
12337 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12339 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12341 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12343 if (layerindex == 0)
12344 GL_AlphaTest(true);
12347 GL_AlphaTest(false);
12348 GL_DepthFunc(GL_EQUAL);
12351 GL_DepthMask(layer->depthmask && writedepth);
12352 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12353 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12354 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12355 switch (layer->type)
12357 case TEXTURELAYERTYPE_LITTEXTURE:
12358 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12360 // two-pass lit texture with 2x rgbscale
12361 // first the lightmap pass
12362 R_Mesh_TexBind(0, r_texture_white);
12363 R_Mesh_TexMatrix(0, NULL);
12364 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12365 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12367 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12368 else if (rsurface.uselightmaptexture)
12369 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12371 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12372 // then apply the texture to it
12373 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12374 R_Mesh_TexBind(0, layer->texture);
12375 R_Mesh_TexMatrix(0, &layer->texmatrix);
12376 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12377 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12378 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);
12382 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12383 R_Mesh_TexBind(0, layer->texture);
12384 R_Mesh_TexMatrix(0, &layer->texmatrix);
12385 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12386 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12388 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);
12390 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);
12393 case TEXTURELAYERTYPE_TEXTURE:
12394 // singletexture unlit texture with transparency support
12395 R_Mesh_TexBind(0, layer->texture);
12396 R_Mesh_TexMatrix(0, &layer->texmatrix);
12397 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12398 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12399 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);
12401 case TEXTURELAYERTYPE_FOG:
12402 // singletexture fogging
12403 if (layer->texture)
12405 R_Mesh_TexBind(0, layer->texture);
12406 R_Mesh_TexMatrix(0, &layer->texmatrix);
12407 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12408 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12412 R_Mesh_TexBind(0, 0);
12413 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12415 // generate a color array for the fog pass
12416 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12417 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12421 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12424 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12426 GL_DepthFunc(GL_LEQUAL);
12427 GL_AlphaTest(false);
12431 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12435 r_vertexgeneric_t *batchvertex;
12438 GL_AlphaTest(false);
12439 R_Mesh_ResetTextureState();
12440 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12442 if(rsurface.texture && rsurface.texture->currentskinframe)
12444 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12445 c[3] *= rsurface.texture->currentalpha;
12455 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12457 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12458 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12459 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12462 // brighten it up (as texture value 127 means "unlit")
12463 c[0] *= 2 * r_refdef.view.colorscale;
12464 c[1] *= 2 * r_refdef.view.colorscale;
12465 c[2] *= 2 * r_refdef.view.colorscale;
12467 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12468 c[3] *= r_wateralpha.value;
12470 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12472 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12473 GL_DepthMask(false);
12475 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12477 GL_BlendFunc(GL_ONE, GL_ONE);
12478 GL_DepthMask(false);
12480 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12482 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12483 GL_DepthMask(false);
12485 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12487 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12488 GL_DepthMask(false);
12492 GL_BlendFunc(GL_ONE, GL_ZERO);
12493 GL_DepthMask(writedepth);
12496 if (r_showsurfaces.integer == 3)
12498 rsurface.passcolor4f = NULL;
12500 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12502 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12504 rsurface.passcolor4f = NULL;
12505 rsurface.passcolor4f_vertexbuffer = 0;
12506 rsurface.passcolor4f_bufferoffset = 0;
12508 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12510 qboolean applycolor = true;
12513 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12515 r_refdef.lightmapintensity = 1;
12516 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12517 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12521 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12523 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12524 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12525 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12528 if(!rsurface.passcolor4f)
12529 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12531 RSurf_DrawBatch_GL11_ApplyAmbient();
12532 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12533 if(r_refdef.fogenabled)
12534 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12535 RSurf_DrawBatch_GL11_ClampColor();
12537 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12538 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12541 else if (!r_refdef.view.showdebug)
12543 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12544 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12545 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12547 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12548 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12550 R_Mesh_PrepareVertices_Generic_Unlock();
12553 else if (r_showsurfaces.integer == 4)
12555 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12556 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12557 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12559 unsigned char c = vi << 3;
12560 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12561 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12563 R_Mesh_PrepareVertices_Generic_Unlock();
12566 else if (r_showsurfaces.integer == 2)
12569 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12570 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12571 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12573 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12574 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12575 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12576 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12577 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12578 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12579 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12581 R_Mesh_PrepareVertices_Generic_Unlock();
12582 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12586 int texturesurfaceindex;
12588 const msurface_t *surface;
12589 unsigned char surfacecolor4ub[4];
12590 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12591 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12593 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12595 surface = texturesurfacelist[texturesurfaceindex];
12596 k = (int)(((size_t)surface) / sizeof(msurface_t));
12597 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12598 for (j = 0;j < surface->num_vertices;j++)
12600 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12601 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12605 R_Mesh_PrepareVertices_Generic_Unlock();
12610 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12613 RSurf_SetupDepthAndCulling();
12614 if (r_showsurfaces.integer)
12616 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12619 switch (vid.renderpath)
12621 case RENDERPATH_GL20:
12622 case RENDERPATH_CGGL:
12623 case RENDERPATH_D3D9:
12624 case RENDERPATH_D3D10:
12625 case RENDERPATH_D3D11:
12626 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12628 case RENDERPATH_GL13:
12629 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12631 case RENDERPATH_GL11:
12632 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12638 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12641 RSurf_SetupDepthAndCulling();
12642 if (r_showsurfaces.integer)
12644 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12647 switch (vid.renderpath)
12649 case RENDERPATH_GL20:
12650 case RENDERPATH_CGGL:
12651 case RENDERPATH_D3D9:
12652 case RENDERPATH_D3D10:
12653 case RENDERPATH_D3D11:
12654 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12656 case RENDERPATH_GL13:
12657 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12659 case RENDERPATH_GL11:
12660 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12666 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12669 int texturenumsurfaces, endsurface;
12670 texture_t *texture;
12671 const msurface_t *surface;
12672 #define MAXBATCH_TRANSPARENTSURFACES 256
12673 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12675 // if the model is static it doesn't matter what value we give for
12676 // wantnormals and wanttangents, so this logic uses only rules applicable
12677 // to a model, knowing that they are meaningless otherwise
12678 if (ent == r_refdef.scene.worldentity)
12679 RSurf_ActiveWorldEntity();
12680 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12681 RSurf_ActiveModelEntity(ent, false, false, false);
12684 switch (vid.renderpath)
12686 case RENDERPATH_GL20:
12687 case RENDERPATH_CGGL:
12688 case RENDERPATH_D3D9:
12689 case RENDERPATH_D3D10:
12690 case RENDERPATH_D3D11:
12691 RSurf_ActiveModelEntity(ent, true, true, false);
12693 case RENDERPATH_GL13:
12694 case RENDERPATH_GL11:
12695 RSurf_ActiveModelEntity(ent, true, false, false);
12700 if (r_transparentdepthmasking.integer)
12702 qboolean setup = false;
12703 for (i = 0;i < numsurfaces;i = j)
12706 surface = rsurface.modelsurfaces + surfacelist[i];
12707 texture = surface->texture;
12708 rsurface.texture = R_GetCurrentTexture(texture);
12709 rsurface.lightmaptexture = NULL;
12710 rsurface.deluxemaptexture = NULL;
12711 rsurface.uselightmaptexture = false;
12712 // scan ahead until we find a different texture
12713 endsurface = min(i + 1024, numsurfaces);
12714 texturenumsurfaces = 0;
12715 texturesurfacelist[texturenumsurfaces++] = surface;
12716 for (;j < endsurface;j++)
12718 surface = rsurface.modelsurfaces + surfacelist[j];
12719 if (texture != surface->texture)
12721 texturesurfacelist[texturenumsurfaces++] = surface;
12723 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12725 // render the range of surfaces as depth
12729 GL_ColorMask(0,0,0,0);
12731 GL_DepthTest(true);
12732 GL_BlendFunc(GL_ONE, GL_ZERO);
12733 GL_DepthMask(true);
12734 GL_AlphaTest(false);
12735 R_Mesh_ResetTextureState();
12736 R_SetupShader_DepthOrShadow();
12738 RSurf_SetupDepthAndCulling();
12739 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12740 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12744 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12747 for (i = 0;i < numsurfaces;i = j)
12750 surface = rsurface.modelsurfaces + surfacelist[i];
12751 texture = surface->texture;
12752 rsurface.texture = R_GetCurrentTexture(texture);
12753 rsurface.lightmaptexture = surface->lightmaptexture;
12754 rsurface.deluxemaptexture = surface->deluxemaptexture;
12755 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12756 // scan ahead until we find a different texture
12757 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12758 texturenumsurfaces = 0;
12759 texturesurfacelist[texturenumsurfaces++] = surface;
12760 for (;j < endsurface;j++)
12762 surface = rsurface.modelsurfaces + surfacelist[j];
12763 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12765 texturesurfacelist[texturenumsurfaces++] = surface;
12767 // render the range of surfaces
12768 if (ent == r_refdef.scene.worldentity)
12769 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12771 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12773 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12774 GL_AlphaTest(false);
12777 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12779 // transparent surfaces get pushed off into the transparent queue
12780 int surfacelistindex;
12781 const msurface_t *surface;
12782 vec3_t tempcenter, center;
12783 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12785 surface = texturesurfacelist[surfacelistindex];
12786 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12787 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12788 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12789 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12790 if (queueentity->transparent_offset) // transparent offset
12792 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12793 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12794 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12796 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12800 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12802 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12804 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12806 RSurf_SetupDepthAndCulling();
12807 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12808 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12812 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12814 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12817 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12820 if (!rsurface.texture->currentnumlayers)
12822 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12823 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12825 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12827 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12828 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12829 else if (!rsurface.texture->currentnumlayers)
12831 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12833 // in the deferred case, transparent surfaces were queued during prepass
12834 if (!r_shadow_usingdeferredprepass)
12835 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12839 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12840 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12845 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12848 texture_t *texture;
12849 // break the surface list down into batches by texture and use of lightmapping
12850 for (i = 0;i < numsurfaces;i = j)
12853 // texture is the base texture pointer, rsurface.texture is the
12854 // current frame/skin the texture is directing us to use (for example
12855 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12856 // use skin 1 instead)
12857 texture = surfacelist[i]->texture;
12858 rsurface.texture = R_GetCurrentTexture(texture);
12859 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12860 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12861 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12862 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12864 // if this texture is not the kind we want, skip ahead to the next one
12865 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12869 // simply scan ahead until we find a different texture or lightmap state
12870 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12872 // render the range of surfaces
12873 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12877 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12881 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12884 if (!rsurface.texture->currentnumlayers)
12886 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12887 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12889 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12891 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12892 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12893 else if (!rsurface.texture->currentnumlayers)
12895 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12897 // in the deferred case, transparent surfaces were queued during prepass
12898 if (!r_shadow_usingdeferredprepass)
12899 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12903 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12904 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12909 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12912 texture_t *texture;
12913 // break the surface list down into batches by texture and use of lightmapping
12914 for (i = 0;i < numsurfaces;i = j)
12917 // texture is the base texture pointer, rsurface.texture is the
12918 // current frame/skin the texture is directing us to use (for example
12919 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12920 // use skin 1 instead)
12921 texture = surfacelist[i]->texture;
12922 rsurface.texture = R_GetCurrentTexture(texture);
12923 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12924 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12925 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12926 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12928 // if this texture is not the kind we want, skip ahead to the next one
12929 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12933 // simply scan ahead until we find a different texture or lightmap state
12934 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12936 // render the range of surfaces
12937 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12941 float locboxvertex3f[6*4*3] =
12943 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12944 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12945 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12946 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12947 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12948 1,0,0, 0,0,0, 0,1,0, 1,1,0
12951 unsigned short locboxelements[6*2*3] =
12956 12,13,14, 12,14,15,
12957 16,17,18, 16,18,19,
12961 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12964 cl_locnode_t *loc = (cl_locnode_t *)ent;
12966 float vertex3f[6*4*3];
12968 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12969 GL_DepthMask(false);
12970 GL_DepthRange(0, 1);
12971 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12972 GL_DepthTest(true);
12973 GL_CullFace(GL_NONE);
12974 R_EntityMatrix(&identitymatrix);
12976 R_Mesh_ResetTextureState();
12978 i = surfacelist[0];
12979 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12980 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12981 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12982 surfacelist[0] < 0 ? 0.5f : 0.125f);
12984 if (VectorCompare(loc->mins, loc->maxs))
12986 VectorSet(size, 2, 2, 2);
12987 VectorMA(loc->mins, -0.5f, size, mins);
12991 VectorCopy(loc->mins, mins);
12992 VectorSubtract(loc->maxs, loc->mins, size);
12995 for (i = 0;i < 6*4*3;)
12996 for (j = 0;j < 3;j++, i++)
12997 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12999 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13000 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13001 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13004 void R_DrawLocs(void)
13007 cl_locnode_t *loc, *nearestloc;
13009 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13010 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13012 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13013 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13017 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13019 if (decalsystem->decals)
13020 Mem_Free(decalsystem->decals);
13021 memset(decalsystem, 0, sizeof(*decalsystem));
13024 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)
13027 tridecal_t *decals;
13030 // expand or initialize the system
13031 if (decalsystem->maxdecals <= decalsystem->numdecals)
13033 decalsystem_t old = *decalsystem;
13034 qboolean useshortelements;
13035 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13036 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13037 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)));
13038 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13039 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13040 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13041 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13042 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13043 if (decalsystem->numdecals)
13044 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13046 Mem_Free(old.decals);
13047 for (i = 0;i < decalsystem->maxdecals*3;i++)
13048 decalsystem->element3i[i] = i;
13049 if (useshortelements)
13050 for (i = 0;i < decalsystem->maxdecals*3;i++)
13051 decalsystem->element3s[i] = i;
13054 // grab a decal and search for another free slot for the next one
13055 decals = decalsystem->decals;
13056 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13057 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13059 decalsystem->freedecal = i;
13060 if (decalsystem->numdecals <= i)
13061 decalsystem->numdecals = i + 1;
13063 // initialize the decal
13065 decal->triangleindex = triangleindex;
13066 decal->surfaceindex = surfaceindex;
13067 decal->decalsequence = decalsequence;
13068 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13069 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13070 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13071 decal->color4ub[0][3] = 255;
13072 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13073 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13074 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13075 decal->color4ub[1][3] = 255;
13076 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13077 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13078 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13079 decal->color4ub[2][3] = 255;
13080 decal->vertex3f[0][0] = v0[0];
13081 decal->vertex3f[0][1] = v0[1];
13082 decal->vertex3f[0][2] = v0[2];
13083 decal->vertex3f[1][0] = v1[0];
13084 decal->vertex3f[1][1] = v1[1];
13085 decal->vertex3f[1][2] = v1[2];
13086 decal->vertex3f[2][0] = v2[0];
13087 decal->vertex3f[2][1] = v2[1];
13088 decal->vertex3f[2][2] = v2[2];
13089 decal->texcoord2f[0][0] = t0[0];
13090 decal->texcoord2f[0][1] = t0[1];
13091 decal->texcoord2f[1][0] = t1[0];
13092 decal->texcoord2f[1][1] = t1[1];
13093 decal->texcoord2f[2][0] = t2[0];
13094 decal->texcoord2f[2][1] = t2[1];
13097 extern cvar_t cl_decals_bias;
13098 extern cvar_t cl_decals_models;
13099 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13100 // baseparms, parms, temps
13101 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)
13106 const float *vertex3f;
13108 float points[2][9][3];
13115 e = rsurface.modelelement3i + 3*triangleindex;
13117 vertex3f = rsurface.modelvertex3f;
13119 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13121 index = 3*e[cornerindex];
13122 VectorCopy(vertex3f + index, v[cornerindex]);
13125 //TriangleNormal(v[0], v[1], v[2], normal);
13126 //if (DotProduct(normal, localnormal) < 0.0f)
13128 // clip by each of the box planes formed from the projection matrix
13129 // if anything survives, we emit the decal
13130 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]);
13133 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]);
13136 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]);
13139 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]);
13142 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]);
13145 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]);
13148 // some part of the triangle survived, so we have to accept it...
13151 // dynamic always uses the original triangle
13153 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13155 index = 3*e[cornerindex];
13156 VectorCopy(vertex3f + index, v[cornerindex]);
13159 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13161 // convert vertex positions to texcoords
13162 Matrix4x4_Transform(projection, v[cornerindex], temp);
13163 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13164 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13165 // calculate distance fade from the projection origin
13166 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13167 f = bound(0.0f, f, 1.0f);
13168 c[cornerindex][0] = r * f;
13169 c[cornerindex][1] = g * f;
13170 c[cornerindex][2] = b * f;
13171 c[cornerindex][3] = 1.0f;
13172 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13175 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);
13177 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13178 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);
13180 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)
13182 matrix4x4_t projection;
13183 decalsystem_t *decalsystem;
13186 const msurface_t *surface;
13187 const msurface_t *surfaces;
13188 const int *surfacelist;
13189 const texture_t *texture;
13191 int numsurfacelist;
13192 int surfacelistindex;
13195 float localorigin[3];
13196 float localnormal[3];
13197 float localmins[3];
13198 float localmaxs[3];
13201 float planes[6][4];
13204 int bih_triangles_count;
13205 int bih_triangles[256];
13206 int bih_surfaces[256];
13208 decalsystem = &ent->decalsystem;
13209 model = ent->model;
13210 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13212 R_DecalSystem_Reset(&ent->decalsystem);
13216 if (!model->brush.data_leafs && !cl_decals_models.integer)
13218 if (decalsystem->model)
13219 R_DecalSystem_Reset(decalsystem);
13223 if (decalsystem->model != model)
13224 R_DecalSystem_Reset(decalsystem);
13225 decalsystem->model = model;
13227 RSurf_ActiveModelEntity(ent, false, false, false);
13229 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13230 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13231 VectorNormalize(localnormal);
13232 localsize = worldsize*rsurface.inversematrixscale;
13233 localmins[0] = localorigin[0] - localsize;
13234 localmins[1] = localorigin[1] - localsize;
13235 localmins[2] = localorigin[2] - localsize;
13236 localmaxs[0] = localorigin[0] + localsize;
13237 localmaxs[1] = localorigin[1] + localsize;
13238 localmaxs[2] = localorigin[2] + localsize;
13240 //VectorCopy(localnormal, planes[4]);
13241 //VectorVectors(planes[4], planes[2], planes[0]);
13242 AnglesFromVectors(angles, localnormal, NULL, false);
13243 AngleVectors(angles, planes[0], planes[2], planes[4]);
13244 VectorNegate(planes[0], planes[1]);
13245 VectorNegate(planes[2], planes[3]);
13246 VectorNegate(planes[4], planes[5]);
13247 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13248 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13249 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13250 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13251 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13252 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13257 matrix4x4_t forwardprojection;
13258 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13259 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13264 float projectionvector[4][3];
13265 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13266 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13267 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13268 projectionvector[0][0] = planes[0][0] * ilocalsize;
13269 projectionvector[0][1] = planes[1][0] * ilocalsize;
13270 projectionvector[0][2] = planes[2][0] * ilocalsize;
13271 projectionvector[1][0] = planes[0][1] * ilocalsize;
13272 projectionvector[1][1] = planes[1][1] * ilocalsize;
13273 projectionvector[1][2] = planes[2][1] * ilocalsize;
13274 projectionvector[2][0] = planes[0][2] * ilocalsize;
13275 projectionvector[2][1] = planes[1][2] * ilocalsize;
13276 projectionvector[2][2] = planes[2][2] * ilocalsize;
13277 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13278 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13279 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13280 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13284 dynamic = model->surfmesh.isanimated;
13285 numsurfacelist = model->nummodelsurfaces;
13286 surfacelist = model->sortedmodelsurfaces;
13287 surfaces = model->data_surfaces;
13290 bih_triangles_count = -1;
13293 if(model->render_bih.numleafs)
13294 bih = &model->render_bih;
13295 else if(model->collision_bih.numleafs)
13296 bih = &model->collision_bih;
13299 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13300 if(bih_triangles_count == 0)
13302 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13304 if(bih_triangles_count > 0)
13306 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13308 surfaceindex = bih_surfaces[triangleindex];
13309 surface = surfaces + surfaceindex;
13310 texture = surface->texture;
13311 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13313 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13315 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13320 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13322 surfaceindex = surfacelist[surfacelistindex];
13323 surface = surfaces + surfaceindex;
13324 // check cull box first because it rejects more than any other check
13325 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13327 // skip transparent surfaces
13328 texture = surface->texture;
13329 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13331 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13333 numtriangles = surface->num_triangles;
13334 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13335 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13340 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13341 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)
13343 int renderentityindex;
13344 float worldmins[3];
13345 float worldmaxs[3];
13346 entity_render_t *ent;
13348 if (!cl_decals_newsystem.integer)
13351 worldmins[0] = worldorigin[0] - worldsize;
13352 worldmins[1] = worldorigin[1] - worldsize;
13353 worldmins[2] = worldorigin[2] - worldsize;
13354 worldmaxs[0] = worldorigin[0] + worldsize;
13355 worldmaxs[1] = worldorigin[1] + worldsize;
13356 worldmaxs[2] = worldorigin[2] + worldsize;
13358 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13360 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13362 ent = r_refdef.scene.entities[renderentityindex];
13363 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13366 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13370 typedef struct r_decalsystem_splatqueue_s
13372 vec3_t worldorigin;
13373 vec3_t worldnormal;
13379 r_decalsystem_splatqueue_t;
13381 int r_decalsystem_numqueued = 0;
13382 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13384 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)
13386 r_decalsystem_splatqueue_t *queue;
13388 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13391 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13392 VectorCopy(worldorigin, queue->worldorigin);
13393 VectorCopy(worldnormal, queue->worldnormal);
13394 Vector4Set(queue->color, r, g, b, a);
13395 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13396 queue->worldsize = worldsize;
13397 queue->decalsequence = cl.decalsequence++;
13400 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13403 r_decalsystem_splatqueue_t *queue;
13405 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13406 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);
13407 r_decalsystem_numqueued = 0;
13410 extern cvar_t cl_decals_max;
13411 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13414 decalsystem_t *decalsystem = &ent->decalsystem;
13421 if (!decalsystem->numdecals)
13424 if (r_showsurfaces.integer)
13427 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13429 R_DecalSystem_Reset(decalsystem);
13433 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13434 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13436 if (decalsystem->lastupdatetime)
13437 frametime = (cl.time - decalsystem->lastupdatetime);
13440 decalsystem->lastupdatetime = cl.time;
13441 decal = decalsystem->decals;
13442 numdecals = decalsystem->numdecals;
13444 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13446 if (decal->color4ub[0][3])
13448 decal->lived += frametime;
13449 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13451 memset(decal, 0, sizeof(*decal));
13452 if (decalsystem->freedecal > i)
13453 decalsystem->freedecal = i;
13457 decal = decalsystem->decals;
13458 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13461 // collapse the array by shuffling the tail decals into the gaps
13464 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13465 decalsystem->freedecal++;
13466 if (decalsystem->freedecal == numdecals)
13468 decal[decalsystem->freedecal] = decal[--numdecals];
13471 decalsystem->numdecals = numdecals;
13473 if (numdecals <= 0)
13475 // if there are no decals left, reset decalsystem
13476 R_DecalSystem_Reset(decalsystem);
13480 extern skinframe_t *decalskinframe;
13481 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13484 decalsystem_t *decalsystem = &ent->decalsystem;
13493 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13496 numdecals = decalsystem->numdecals;
13500 if (r_showsurfaces.integer)
13503 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13505 R_DecalSystem_Reset(decalsystem);
13509 // if the model is static it doesn't matter what value we give for
13510 // wantnormals and wanttangents, so this logic uses only rules applicable
13511 // to a model, knowing that they are meaningless otherwise
13512 if (ent == r_refdef.scene.worldentity)
13513 RSurf_ActiveWorldEntity();
13515 RSurf_ActiveModelEntity(ent, false, false, false);
13517 decalsystem->lastupdatetime = cl.time;
13518 decal = decalsystem->decals;
13520 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13522 // update vertex positions for animated models
13523 v3f = decalsystem->vertex3f;
13524 c4f = decalsystem->color4f;
13525 t2f = decalsystem->texcoord2f;
13526 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13528 if (!decal->color4ub[0][3])
13531 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13534 // update color values for fading decals
13535 if (decal->lived >= cl_decals_time.value)
13537 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13538 alpha *= (1.0f/255.0f);
13541 alpha = 1.0f/255.0f;
13543 c4f[ 0] = decal->color4ub[0][0] * alpha;
13544 c4f[ 1] = decal->color4ub[0][1] * alpha;
13545 c4f[ 2] = decal->color4ub[0][2] * alpha;
13547 c4f[ 4] = decal->color4ub[1][0] * alpha;
13548 c4f[ 5] = decal->color4ub[1][1] * alpha;
13549 c4f[ 6] = decal->color4ub[1][2] * alpha;
13551 c4f[ 8] = decal->color4ub[2][0] * alpha;
13552 c4f[ 9] = decal->color4ub[2][1] * alpha;
13553 c4f[10] = decal->color4ub[2][2] * alpha;
13556 t2f[0] = decal->texcoord2f[0][0];
13557 t2f[1] = decal->texcoord2f[0][1];
13558 t2f[2] = decal->texcoord2f[1][0];
13559 t2f[3] = decal->texcoord2f[1][1];
13560 t2f[4] = decal->texcoord2f[2][0];
13561 t2f[5] = decal->texcoord2f[2][1];
13563 // update vertex positions for animated models
13564 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13566 e = rsurface.modelelement3i + 3*decal->triangleindex;
13567 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13568 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13569 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13573 VectorCopy(decal->vertex3f[0], v3f);
13574 VectorCopy(decal->vertex3f[1], v3f + 3);
13575 VectorCopy(decal->vertex3f[2], v3f + 6);
13578 if (r_refdef.fogenabled)
13580 alpha = RSurf_FogVertex(v3f);
13581 VectorScale(c4f, alpha, c4f);
13582 alpha = RSurf_FogVertex(v3f + 3);
13583 VectorScale(c4f + 4, alpha, c4f + 4);
13584 alpha = RSurf_FogVertex(v3f + 6);
13585 VectorScale(c4f + 8, alpha, c4f + 8);
13596 r_refdef.stats.drawndecals += numtris;
13598 // now render the decals all at once
13599 // (this assumes they all use one particle font texture!)
13600 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);
13601 R_Mesh_ResetTextureState();
13602 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13603 GL_DepthMask(false);
13604 GL_DepthRange(0, 1);
13605 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13606 GL_DepthTest(true);
13607 GL_CullFace(GL_NONE);
13608 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13609 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13610 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13614 static void R_DrawModelDecals(void)
13618 // fade faster when there are too many decals
13619 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13620 for (i = 0;i < r_refdef.scene.numentities;i++)
13621 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13623 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13624 for (i = 0;i < r_refdef.scene.numentities;i++)
13625 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13626 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13628 R_DecalSystem_ApplySplatEntitiesQueue();
13630 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13631 for (i = 0;i < r_refdef.scene.numentities;i++)
13632 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13634 r_refdef.stats.totaldecals += numdecals;
13636 if (r_showsurfaces.integer)
13639 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13641 for (i = 0;i < r_refdef.scene.numentities;i++)
13643 if (!r_refdef.viewcache.entityvisible[i])
13645 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13646 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13650 extern cvar_t mod_collision_bih;
13651 void R_DrawDebugModel(void)
13653 entity_render_t *ent = rsurface.entity;
13654 int i, j, k, l, flagsmask;
13655 const msurface_t *surface;
13656 dp_model_t *model = ent->model;
13659 switch(vid.renderpath)
13661 case RENDERPATH_GL11:
13662 case RENDERPATH_GL13:
13663 case RENDERPATH_GL20:
13664 case RENDERPATH_CGGL:
13666 case RENDERPATH_D3D9:
13667 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13669 case RENDERPATH_D3D10:
13670 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13672 case RENDERPATH_D3D11:
13673 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13677 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13679 R_Mesh_ResetTextureState();
13680 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13681 GL_DepthRange(0, 1);
13682 GL_DepthTest(!r_showdisabledepthtest.integer);
13683 GL_DepthMask(false);
13684 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13686 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13690 qboolean cullbox = ent == r_refdef.scene.worldentity;
13691 const q3mbrush_t *brush;
13692 const bih_t *bih = &model->collision_bih;
13693 const bih_leaf_t *bihleaf;
13694 float vertex3f[3][3];
13695 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13697 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13699 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13701 switch (bihleaf->type)
13704 brush = model->brush.data_brushes + bihleaf->itemindex;
13705 if (brush->colbrushf && brush->colbrushf->numtriangles)
13707 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);
13708 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13709 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13712 case BIH_COLLISIONTRIANGLE:
13713 triangleindex = bihleaf->itemindex;
13714 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13715 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13716 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13717 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);
13718 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13719 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13721 case BIH_RENDERTRIANGLE:
13722 triangleindex = bihleaf->itemindex;
13723 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13724 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13725 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13726 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);
13727 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13728 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13734 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13736 if (r_showtris.integer || r_shownormals.integer)
13738 if (r_showdisabledepthtest.integer)
13740 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13741 GL_DepthMask(false);
13745 GL_BlendFunc(GL_ONE, GL_ZERO);
13746 GL_DepthMask(true);
13748 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13750 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13752 rsurface.texture = R_GetCurrentTexture(surface->texture);
13753 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13755 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13756 if (r_showtris.value > 0)
13758 if (!rsurface.texture->currentlayers->depthmask)
13759 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13760 else if (ent == r_refdef.scene.worldentity)
13761 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13763 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13764 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13765 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13767 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13770 if (r_shownormals.value < 0)
13772 qglBegin(GL_LINES);
13773 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13775 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13776 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13777 qglVertex3f(v[0], v[1], v[2]);
13778 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13779 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13780 qglVertex3f(v[0], v[1], v[2]);
13785 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13787 qglBegin(GL_LINES);
13788 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13790 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13791 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13792 qglVertex3f(v[0], v[1], v[2]);
13793 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13794 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13795 qglVertex3f(v[0], v[1], v[2]);
13799 qglBegin(GL_LINES);
13800 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13802 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13803 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13804 qglVertex3f(v[0], v[1], v[2]);
13805 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13806 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13807 qglVertex3f(v[0], v[1], v[2]);
13811 qglBegin(GL_LINES);
13812 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13814 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13815 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13816 qglVertex3f(v[0], v[1], v[2]);
13817 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13818 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13819 qglVertex3f(v[0], v[1], v[2]);
13826 rsurface.texture = NULL;
13830 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13831 int r_maxsurfacelist = 0;
13832 const msurface_t **r_surfacelist = NULL;
13833 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13835 int i, j, endj, flagsmask;
13836 dp_model_t *model = r_refdef.scene.worldmodel;
13837 msurface_t *surfaces;
13838 unsigned char *update;
13839 int numsurfacelist = 0;
13843 if (r_maxsurfacelist < model->num_surfaces)
13845 r_maxsurfacelist = model->num_surfaces;
13847 Mem_Free((msurface_t**)r_surfacelist);
13848 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13851 RSurf_ActiveWorldEntity();
13853 surfaces = model->data_surfaces;
13854 update = model->brushq1.lightmapupdateflags;
13856 // update light styles on this submodel
13857 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13859 model_brush_lightstyleinfo_t *style;
13860 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13862 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13864 int *list = style->surfacelist;
13865 style->value = r_refdef.scene.lightstylevalue[style->style];
13866 for (j = 0;j < style->numsurfaces;j++)
13867 update[list[j]] = true;
13872 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13876 R_DrawDebugModel();
13877 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13881 rsurface.lightmaptexture = NULL;
13882 rsurface.deluxemaptexture = NULL;
13883 rsurface.uselightmaptexture = false;
13884 rsurface.texture = NULL;
13885 rsurface.rtlight = NULL;
13886 numsurfacelist = 0;
13887 // add visible surfaces to draw list
13888 for (i = 0;i < model->nummodelsurfaces;i++)
13890 j = model->sortedmodelsurfaces[i];
13891 if (r_refdef.viewcache.world_surfacevisible[j])
13892 r_surfacelist[numsurfacelist++] = surfaces + j;
13894 // update lightmaps if needed
13895 if (model->brushq1.firstrender)
13897 model->brushq1.firstrender = false;
13898 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13900 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13904 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13905 if (r_refdef.viewcache.world_surfacevisible[j])
13907 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13909 // don't do anything if there were no surfaces
13910 if (!numsurfacelist)
13912 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13915 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13916 GL_AlphaTest(false);
13918 // add to stats if desired
13919 if (r_speeds.integer && !skysurfaces && !depthonly)
13921 r_refdef.stats.world_surfaces += numsurfacelist;
13922 for (j = 0;j < numsurfacelist;j++)
13923 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13926 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13929 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13931 int i, j, endj, flagsmask;
13932 dp_model_t *model = ent->model;
13933 msurface_t *surfaces;
13934 unsigned char *update;
13935 int numsurfacelist = 0;
13939 if (r_maxsurfacelist < model->num_surfaces)
13941 r_maxsurfacelist = model->num_surfaces;
13943 Mem_Free((msurface_t **)r_surfacelist);
13944 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13947 // if the model is static it doesn't matter what value we give for
13948 // wantnormals and wanttangents, so this logic uses only rules applicable
13949 // to a model, knowing that they are meaningless otherwise
13950 if (ent == r_refdef.scene.worldentity)
13951 RSurf_ActiveWorldEntity();
13952 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13953 RSurf_ActiveModelEntity(ent, false, false, false);
13955 RSurf_ActiveModelEntity(ent, true, true, true);
13956 else if (depthonly)
13958 switch (vid.renderpath)
13960 case RENDERPATH_GL20:
13961 case RENDERPATH_CGGL:
13962 case RENDERPATH_D3D9:
13963 case RENDERPATH_D3D10:
13964 case RENDERPATH_D3D11:
13965 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13967 case RENDERPATH_GL13:
13968 case RENDERPATH_GL11:
13969 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13975 switch (vid.renderpath)
13977 case RENDERPATH_GL20:
13978 case RENDERPATH_CGGL:
13979 case RENDERPATH_D3D9:
13980 case RENDERPATH_D3D10:
13981 case RENDERPATH_D3D11:
13982 RSurf_ActiveModelEntity(ent, true, true, false);
13984 case RENDERPATH_GL13:
13985 case RENDERPATH_GL11:
13986 RSurf_ActiveModelEntity(ent, true, false, false);
13991 surfaces = model->data_surfaces;
13992 update = model->brushq1.lightmapupdateflags;
13994 // update light styles
13995 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13997 model_brush_lightstyleinfo_t *style;
13998 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14000 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14002 int *list = style->surfacelist;
14003 style->value = r_refdef.scene.lightstylevalue[style->style];
14004 for (j = 0;j < style->numsurfaces;j++)
14005 update[list[j]] = true;
14010 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14014 R_DrawDebugModel();
14015 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14019 rsurface.lightmaptexture = NULL;
14020 rsurface.deluxemaptexture = NULL;
14021 rsurface.uselightmaptexture = false;
14022 rsurface.texture = NULL;
14023 rsurface.rtlight = NULL;
14024 numsurfacelist = 0;
14025 // add visible surfaces to draw list
14026 for (i = 0;i < model->nummodelsurfaces;i++)
14027 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14028 // don't do anything if there were no surfaces
14029 if (!numsurfacelist)
14031 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14034 // update lightmaps if needed
14038 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14043 R_BuildLightMap(ent, surfaces + j);
14048 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14050 R_BuildLightMap(ent, surfaces + j);
14051 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14052 GL_AlphaTest(false);
14054 // add to stats if desired
14055 if (r_speeds.integer && !skysurfaces && !depthonly)
14057 r_refdef.stats.entities_surfaces += numsurfacelist;
14058 for (j = 0;j < numsurfacelist;j++)
14059 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14062 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14065 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14067 static texture_t texture;
14068 static msurface_t surface;
14069 const msurface_t *surfacelist = &surface;
14071 // fake enough texture and surface state to render this geometry
14073 texture.update_lastrenderframe = -1; // regenerate this texture
14074 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14075 texture.currentskinframe = skinframe;
14076 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14077 texture.offsetmapping = OFFSETMAPPING_OFF;
14078 texture.offsetscale = 1;
14079 texture.specularscalemod = 1;
14080 texture.specularpowermod = 1;
14082 surface.texture = &texture;
14083 surface.num_triangles = numtriangles;
14084 surface.num_firsttriangle = firsttriangle;
14085 surface.num_vertices = numvertices;
14086 surface.num_firstvertex = firstvertex;
14089 rsurface.texture = R_GetCurrentTexture(surface.texture);
14090 rsurface.lightmaptexture = NULL;
14091 rsurface.deluxemaptexture = NULL;
14092 rsurface.uselightmaptexture = false;
14093 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14096 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)
14098 static msurface_t surface;
14099 const msurface_t *surfacelist = &surface;
14101 // fake enough texture and surface state to render this geometry
14103 surface.texture = texture;
14104 surface.num_triangles = numtriangles;
14105 surface.num_firsttriangle = firsttriangle;
14106 surface.num_vertices = numvertices;
14107 surface.num_firstvertex = firstvertex;
14110 rsurface.texture = R_GetCurrentTexture(surface.texture);
14111 rsurface.lightmaptexture = NULL;
14112 rsurface.deluxemaptexture = NULL;
14113 rsurface.uselightmaptexture = false;
14114 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);