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 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3077 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3079 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3080 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3081 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3082 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3083 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3084 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3085 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3086 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3087 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3088 "// color.r = half(shadowmaptc.z);\n"
3089 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3090 "// color.r = half(shadowmaptc.z);\n"
3092 "// color.rgb = abs(CubeVector);\n"
3094 "// color.rgb = half3(1,1,1);\n"
3095 "#endif // MODE_LIGHTSOURCE\n"
3100 "#ifdef MODE_LIGHTDIRECTION\n"
3102 "#ifdef USEDIFFUSE\n"
3103 " half3 lightnormal = half3(normalize(LightVector));\n"
3105 "#define lightcolor LightColor\n"
3106 "#endif // MODE_LIGHTDIRECTION\n"
3107 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3109 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3110 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3111 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3112 " // convert modelspace light vector to tangentspace\n"
3113 " half3 lightnormal;\n"
3114 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3115 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3116 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3117 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3118 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3119 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3120 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3121 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3122 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3123 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3124 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3125 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3126 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3127 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3128 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3130 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3131 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3132 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3138 "#ifdef MODE_LIGHTMAP\n"
3139 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3140 "#endif // MODE_LIGHTMAP\n"
3141 "#ifdef MODE_VERTEXCOLOR\n"
3142 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3143 "#endif // MODE_VERTEXCOLOR\n"
3144 "#ifdef MODE_FLATCOLOR\n"
3145 " color.rgb = diffusetex * Color_Ambient;\n"
3146 "#endif // MODE_FLATCOLOR\n"
3152 "# ifdef USEDIFFUSE\n"
3153 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3154 "# ifdef USESPECULAR\n"
3155 "# ifdef USEEXACTSPECULARMATH\n"
3156 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3158 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3159 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3161 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3163 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3166 " color.rgb = diffusetex * Color_Ambient;\n"
3170 "#ifdef USESHADOWMAPORTHO\n"
3171 " color.rgb *= ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale);\n"
3174 "#ifdef USEDEFERREDLIGHTMAP\n"
3175 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3176 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3177 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3181 "#ifdef USEVERTEXTEXTUREBLEND\n"
3182 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3184 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3189 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3192 " // 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"
3193 "#ifdef USEREFLECTION\n"
3194 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3195 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3196 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3197 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3198 " // FIXME temporary hack to detect the case that the reflection\n"
3199 " // gets blackened at edges due to leaving the area that contains actual\n"
3201 " // Remove this 'ack once we have a better way to stop this thing from\n"
3203 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3204 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3205 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3206 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3207 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3208 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3211 " gl_FragColor = float4(color);\n"
3213 "#endif // FRAGMENT_SHADER\n"
3215 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3216 "#endif // !MODE_DEFERREDGEOMETRY\n"
3217 "#endif // !MODE_WATER\n"
3218 "#endif // !MODE_REFRACTION\n"
3219 "#endif // !MODE_BLOOMBLUR\n"
3220 "#endif // !MODE_GENERIC\n"
3221 "#endif // !MODE_POSTPROCESS\n"
3222 "#endif // !MODE_SHOWDEPTH\n"
3223 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3226 char *glslshaderstring = NULL;
3227 char *cgshaderstring = NULL;
3228 char *hlslshaderstring = NULL;
3230 //=======================================================================================================================================================
3232 typedef struct shaderpermutationinfo_s
3234 const char *pretext;
3237 shaderpermutationinfo_t;
3239 typedef struct shadermodeinfo_s
3241 const char *vertexfilename;
3242 const char *geometryfilename;
3243 const char *fragmentfilename;
3244 const char *pretext;
3249 typedef enum shaderpermutation_e
3251 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3252 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3253 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3254 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3255 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3256 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3257 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3258 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3259 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3260 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3261 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3262 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3263 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3264 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3265 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3266 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3267 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3268 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3269 SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3270 SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3271 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3272 SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3273 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3274 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3275 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3276 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3277 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3278 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3279 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3281 shaderpermutation_t;
3283 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3284 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3286 {"#define USEDIFFUSE\n", " diffuse"},
3287 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3288 {"#define USEVIEWTINT\n", " viewtint"},
3289 {"#define USECOLORMAPPING\n", " colormapping"},
3290 {"#define USESATURATION\n", " saturation"},
3291 {"#define USEFOGINSIDE\n", " foginside"},
3292 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3293 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3294 {"#define USEGAMMARAMPS\n", " gammaramps"},
3295 {"#define USECUBEFILTER\n", " cubefilter"},
3296 {"#define USEGLOW\n", " glow"},
3297 {"#define USEBLOOM\n", " bloom"},
3298 {"#define USESPECULAR\n", " specular"},
3299 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3300 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3301 {"#define USEREFLECTION\n", " reflection"},
3302 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3303 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3304 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3305 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3306 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3307 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3308 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3309 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3310 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3311 {"#define USEALPHAKILL\n", " alphakill"},
3312 {"#define USEREFLECTCUBE\n", " reflectcube"},
3315 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3316 typedef enum shadermode_e
3318 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3319 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3320 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3321 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3322 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3323 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3324 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3325 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3326 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3327 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3328 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3329 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3330 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3331 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3332 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3337 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3338 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3340 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3341 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3342 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3343 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3344 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3345 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3346 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3347 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3348 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3349 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3350 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3351 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3352 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3353 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3354 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3358 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3360 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3361 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3362 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3363 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3364 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3365 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3366 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3367 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3368 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3369 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3370 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3371 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3372 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3373 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3374 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3379 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3381 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3382 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3383 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3384 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3385 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3386 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3387 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3388 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3389 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3390 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3391 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3392 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3393 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3394 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3395 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3399 struct r_glsl_permutation_s;
3400 typedef struct r_glsl_permutation_s
3402 /// hash lookup data
3403 struct r_glsl_permutation_s *hashnext;
3405 unsigned int permutation;
3407 /// indicates if we have tried compiling this permutation already
3409 /// 0 if compilation failed
3411 /// locations of detected uniforms in program object, or -1 if not found
3412 int loc_Texture_First;
3413 int loc_Texture_Second;
3414 int loc_Texture_GammaRamps;
3415 int loc_Texture_Normal;
3416 int loc_Texture_Color;
3417 int loc_Texture_Gloss;
3418 int loc_Texture_Glow;
3419 int loc_Texture_SecondaryNormal;
3420 int loc_Texture_SecondaryColor;
3421 int loc_Texture_SecondaryGloss;
3422 int loc_Texture_SecondaryGlow;
3423 int loc_Texture_Pants;
3424 int loc_Texture_Shirt;
3425 int loc_Texture_FogHeightTexture;
3426 int loc_Texture_FogMask;
3427 int loc_Texture_Lightmap;
3428 int loc_Texture_Deluxemap;
3429 int loc_Texture_Attenuation;
3430 int loc_Texture_Cube;
3431 int loc_Texture_Refraction;
3432 int loc_Texture_Reflection;
3433 int loc_Texture_ShadowMap2D;
3434 int loc_Texture_CubeProjection;
3435 int loc_Texture_ScreenDepth;
3436 int loc_Texture_ScreenNormalMap;
3437 int loc_Texture_ScreenDiffuse;
3438 int loc_Texture_ScreenSpecular;
3439 int loc_Texture_ReflectMask;
3440 int loc_Texture_ReflectCube;
3442 int loc_BloomBlur_Parameters;
3444 int loc_Color_Ambient;
3445 int loc_Color_Diffuse;
3446 int loc_Color_Specular;
3448 int loc_Color_Pants;
3449 int loc_Color_Shirt;
3450 int loc_DeferredColor_Ambient;
3451 int loc_DeferredColor_Diffuse;
3452 int loc_DeferredColor_Specular;
3453 int loc_DeferredMod_Diffuse;
3454 int loc_DeferredMod_Specular;
3455 int loc_DistortScaleRefractReflect;
3456 int loc_EyePosition;
3458 int loc_FogHeightFade;
3460 int loc_FogPlaneViewDist;
3461 int loc_FogRangeRecip;
3464 int loc_LightPosition;
3465 int loc_OffsetMapping_Scale;
3467 int loc_ReflectColor;
3468 int loc_ReflectFactor;
3469 int loc_ReflectOffset;
3470 int loc_RefractColor;
3472 int loc_ScreenCenterRefractReflect;
3473 int loc_ScreenScaleRefractReflect;
3474 int loc_ScreenToDepth;
3475 int loc_ShadowMap_Parameters;
3476 int loc_ShadowMap_TextureScale;
3477 int loc_SpecularPower;
3482 int loc_ViewTintColor;
3483 int loc_ViewToLight;
3484 int loc_ModelToLight;
3486 int loc_BackgroundTexMatrix;
3487 int loc_ModelViewProjectionMatrix;
3488 int loc_ModelViewMatrix;
3489 int loc_PixelToScreenTexCoord;
3490 int loc_ModelToReflectCube;
3491 int loc_ShadowMapMatrix;
3492 int loc_BloomColorSubtract;
3494 r_glsl_permutation_t;
3496 #define SHADERPERMUTATION_HASHSIZE 256
3498 /// information about each possible shader permutation
3499 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3500 /// currently selected permutation
3501 r_glsl_permutation_t *r_glsl_permutation;
3502 /// storage for permutations linked in the hash table
3503 memexpandablearray_t r_glsl_permutationarray;
3505 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3507 //unsigned int hashdepth = 0;
3508 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3509 r_glsl_permutation_t *p;
3510 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3512 if (p->mode == mode && p->permutation == permutation)
3514 //if (hashdepth > 10)
3515 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3520 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3522 p->permutation = permutation;
3523 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3524 r_glsl_permutationhash[mode][hashindex] = p;
3525 //if (hashdepth > 10)
3526 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3530 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3533 if (!filename || !filename[0])
3535 if (!strcmp(filename, "glsl/default.glsl"))
3537 if (!glslshaderstring)
3539 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3540 if (glslshaderstring)
3541 Con_DPrintf("Loading shaders from file %s...\n", filename);
3543 glslshaderstring = (char *)builtinshaderstring;
3545 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3546 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3547 return shaderstring;
3549 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3552 if (printfromdisknotice)
3553 Con_DPrintf("from disk %s... ", filename);
3554 return shaderstring;
3556 return shaderstring;
3559 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3562 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3563 int vertstrings_count = 0;
3564 int geomstrings_count = 0;
3565 int fragstrings_count = 0;
3566 char *vertexstring, *geometrystring, *fragmentstring;
3567 const char *vertstrings_list[32+3];
3568 const char *geomstrings_list[32+3];
3569 const char *fragstrings_list[32+3];
3570 char permutationname[256];
3577 permutationname[0] = 0;
3578 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3579 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3580 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3582 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3584 // the first pretext is which type of shader to compile as
3585 // (later these will all be bound together as a program object)
3586 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3587 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3588 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3590 // the second pretext is the mode (for example a light source)
3591 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3592 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3593 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3594 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3596 // now add all the permutation pretexts
3597 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3599 if (permutation & (1<<i))
3601 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3602 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3603 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3604 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3608 // keep line numbers correct
3609 vertstrings_list[vertstrings_count++] = "\n";
3610 geomstrings_list[geomstrings_count++] = "\n";
3611 fragstrings_list[fragstrings_count++] = "\n";
3615 // now append the shader text itself
3616 vertstrings_list[vertstrings_count++] = vertexstring;
3617 geomstrings_list[geomstrings_count++] = geometrystring;
3618 fragstrings_list[fragstrings_count++] = fragmentstring;
3620 // if any sources were NULL, clear the respective list
3622 vertstrings_count = 0;
3623 if (!geometrystring)
3624 geomstrings_count = 0;
3625 if (!fragmentstring)
3626 fragstrings_count = 0;
3628 // compile the shader program
3629 if (vertstrings_count + geomstrings_count + fragstrings_count)
3630 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3634 qglUseProgramObjectARB(p->program);CHECKGLERROR
3635 // look up all the uniform variable names we care about, so we don't
3636 // have to look them up every time we set them
3638 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3639 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3640 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3641 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3642 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3643 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3644 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3645 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3646 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3647 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3648 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3649 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3650 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3651 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3652 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3653 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3654 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3655 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3656 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3657 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3658 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3659 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3660 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3661 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3662 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3663 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3664 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3665 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3666 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3667 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3668 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3669 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3670 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3671 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3672 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3673 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3674 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3675 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3676 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3677 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3678 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3679 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3680 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3681 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3682 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3683 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3684 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3685 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3686 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3687 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3688 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3689 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3690 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3691 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3692 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3693 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3694 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3695 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3696 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3697 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3698 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3699 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3700 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3701 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3702 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3703 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3704 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3705 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3706 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3707 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3708 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3709 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3710 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3711 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3712 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3713 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3714 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3715 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3716 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3717 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3718 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3719 // initialize the samplers to refer to the texture units we use
3720 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3721 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3722 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3723 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3724 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3725 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3726 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3727 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3728 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3729 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3730 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3731 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3732 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3733 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3734 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3735 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3736 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3737 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3738 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3739 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3740 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3741 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3742 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3743 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3744 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3745 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3746 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3747 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3748 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3750 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3753 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3757 Mem_Free(vertexstring);
3759 Mem_Free(geometrystring);
3761 Mem_Free(fragmentstring);
3764 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3766 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3767 if (r_glsl_permutation != perm)
3769 r_glsl_permutation = perm;
3770 if (!r_glsl_permutation->program)
3772 if (!r_glsl_permutation->compiled)
3773 R_GLSL_CompilePermutation(perm, mode, permutation);
3774 if (!r_glsl_permutation->program)
3776 // remove features until we find a valid permutation
3778 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3780 // reduce i more quickly whenever it would not remove any bits
3781 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3782 if (!(permutation & j))
3785 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3786 if (!r_glsl_permutation->compiled)
3787 R_GLSL_CompilePermutation(perm, mode, permutation);
3788 if (r_glsl_permutation->program)
3791 if (i >= SHADERPERMUTATION_COUNT)
3793 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3794 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3795 qglUseProgramObjectARB(0);CHECKGLERROR
3796 return; // no bit left to clear, entire mode is broken
3801 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3803 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3804 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3805 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3809 #include <Cg/cgGL.h>
3810 struct r_cg_permutation_s;
3811 typedef struct r_cg_permutation_s
3813 /// hash lookup data
3814 struct r_cg_permutation_s *hashnext;
3816 unsigned int permutation;
3818 /// indicates if we have tried compiling this permutation already
3820 /// 0 if compilation failed
3823 /// locations of detected parameters in programs, or NULL if not found
3824 CGparameter vp_EyePosition;
3825 CGparameter vp_FogPlane;
3826 CGparameter vp_LightDir;
3827 CGparameter vp_LightPosition;
3828 CGparameter vp_ModelToLight;
3829 CGparameter vp_TexMatrix;
3830 CGparameter vp_BackgroundTexMatrix;
3831 CGparameter vp_ModelViewProjectionMatrix;
3832 CGparameter vp_ModelViewMatrix;
3833 CGparameter vp_ShadowMapMatrix;
3835 CGparameter fp_Texture_First;
3836 CGparameter fp_Texture_Second;
3837 CGparameter fp_Texture_GammaRamps;
3838 CGparameter fp_Texture_Normal;
3839 CGparameter fp_Texture_Color;
3840 CGparameter fp_Texture_Gloss;
3841 CGparameter fp_Texture_Glow;
3842 CGparameter fp_Texture_SecondaryNormal;
3843 CGparameter fp_Texture_SecondaryColor;
3844 CGparameter fp_Texture_SecondaryGloss;
3845 CGparameter fp_Texture_SecondaryGlow;
3846 CGparameter fp_Texture_Pants;
3847 CGparameter fp_Texture_Shirt;
3848 CGparameter fp_Texture_FogHeightTexture;
3849 CGparameter fp_Texture_FogMask;
3850 CGparameter fp_Texture_Lightmap;
3851 CGparameter fp_Texture_Deluxemap;
3852 CGparameter fp_Texture_Attenuation;
3853 CGparameter fp_Texture_Cube;
3854 CGparameter fp_Texture_Refraction;
3855 CGparameter fp_Texture_Reflection;
3856 CGparameter fp_Texture_ShadowMap2D;
3857 CGparameter fp_Texture_CubeProjection;
3858 CGparameter fp_Texture_ScreenDepth;
3859 CGparameter fp_Texture_ScreenNormalMap;
3860 CGparameter fp_Texture_ScreenDiffuse;
3861 CGparameter fp_Texture_ScreenSpecular;
3862 CGparameter fp_Texture_ReflectMask;
3863 CGparameter fp_Texture_ReflectCube;
3864 CGparameter fp_Alpha;
3865 CGparameter fp_BloomBlur_Parameters;
3866 CGparameter fp_ClientTime;
3867 CGparameter fp_Color_Ambient;
3868 CGparameter fp_Color_Diffuse;
3869 CGparameter fp_Color_Specular;
3870 CGparameter fp_Color_Glow;
3871 CGparameter fp_Color_Pants;
3872 CGparameter fp_Color_Shirt;
3873 CGparameter fp_DeferredColor_Ambient;
3874 CGparameter fp_DeferredColor_Diffuse;
3875 CGparameter fp_DeferredColor_Specular;
3876 CGparameter fp_DeferredMod_Diffuse;
3877 CGparameter fp_DeferredMod_Specular;
3878 CGparameter fp_DistortScaleRefractReflect;
3879 CGparameter fp_EyePosition;
3880 CGparameter fp_FogColor;
3881 CGparameter fp_FogHeightFade;
3882 CGparameter fp_FogPlane;
3883 CGparameter fp_FogPlaneViewDist;
3884 CGparameter fp_FogRangeRecip;
3885 CGparameter fp_LightColor;
3886 CGparameter fp_LightDir;
3887 CGparameter fp_LightPosition;
3888 CGparameter fp_OffsetMapping_Scale;
3889 CGparameter fp_PixelSize;
3890 CGparameter fp_ReflectColor;
3891 CGparameter fp_ReflectFactor;
3892 CGparameter fp_ReflectOffset;
3893 CGparameter fp_RefractColor;
3894 CGparameter fp_Saturation;
3895 CGparameter fp_ScreenCenterRefractReflect;
3896 CGparameter fp_ScreenScaleRefractReflect;
3897 CGparameter fp_ScreenToDepth;
3898 CGparameter fp_ShadowMap_Parameters;
3899 CGparameter fp_ShadowMap_TextureScale;
3900 CGparameter fp_SpecularPower;
3901 CGparameter fp_UserVec1;
3902 CGparameter fp_UserVec2;
3903 CGparameter fp_UserVec3;
3904 CGparameter fp_UserVec4;
3905 CGparameter fp_ViewTintColor;
3906 CGparameter fp_ViewToLight;
3907 CGparameter fp_PixelToScreenTexCoord;
3908 CGparameter fp_ModelToReflectCube;
3909 CGparameter fp_BloomColorSubtract;
3913 /// information about each possible shader permutation
3914 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3915 /// currently selected permutation
3916 r_cg_permutation_t *r_cg_permutation;
3917 /// storage for permutations linked in the hash table
3918 memexpandablearray_t r_cg_permutationarray;
3920 #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));}}
3922 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3924 //unsigned int hashdepth = 0;
3925 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3926 r_cg_permutation_t *p;
3927 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3929 if (p->mode == mode && p->permutation == permutation)
3931 //if (hashdepth > 10)
3932 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3937 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3939 p->permutation = permutation;
3940 p->hashnext = r_cg_permutationhash[mode][hashindex];
3941 r_cg_permutationhash[mode][hashindex] = p;
3942 //if (hashdepth > 10)
3943 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3947 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3950 if (!filename || !filename[0])
3952 if (!strcmp(filename, "cg/default.cg"))
3954 if (!cgshaderstring)
3956 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3958 Con_DPrintf("Loading shaders from file %s...\n", filename);
3960 cgshaderstring = (char *)builtincgshaderstring;
3962 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3963 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3964 return shaderstring;
3966 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3969 if (printfromdisknotice)
3970 Con_DPrintf("from disk %s... ", filename);
3971 return shaderstring;
3973 return shaderstring;
3976 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3978 // TODO: load or create .fp and .vp shader files
3981 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3984 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3985 int vertstrings_count = 0, vertstring_length = 0;
3986 int geomstrings_count = 0, geomstring_length = 0;
3987 int fragstrings_count = 0, fragstring_length = 0;
3989 char *vertexstring, *geometrystring, *fragmentstring;
3990 char *vertstring, *geomstring, *fragstring;
3991 const char *vertstrings_list[32+3];
3992 const char *geomstrings_list[32+3];
3993 const char *fragstrings_list[32+3];
3994 char permutationname[256];
3995 char cachename[256];
3996 CGprofile vertexProfile;
3997 CGprofile fragmentProfile;
4005 permutationname[0] = 0;
4007 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4008 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4009 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4011 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4012 strlcat(cachename, "cg/", sizeof(cachename));
4014 // the first pretext is which type of shader to compile as
4015 // (later these will all be bound together as a program object)
4016 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4017 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4018 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4020 // the second pretext is the mode (for example a light source)
4021 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4022 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4023 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4024 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4025 strlcat(cachename, modeinfo->name, sizeof(cachename));
4027 // now add all the permutation pretexts
4028 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4030 if (permutation & (1<<i))
4032 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4033 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4034 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4035 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4036 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4040 // keep line numbers correct
4041 vertstrings_list[vertstrings_count++] = "\n";
4042 geomstrings_list[geomstrings_count++] = "\n";
4043 fragstrings_list[fragstrings_count++] = "\n";
4047 // replace spaces in the cachename with _ characters
4048 for (i = 0;cachename[i];i++)
4049 if (cachename[i] == ' ')
4052 // now append the shader text itself
4053 vertstrings_list[vertstrings_count++] = vertexstring;
4054 geomstrings_list[geomstrings_count++] = geometrystring;
4055 fragstrings_list[fragstrings_count++] = fragmentstring;
4057 // if any sources were NULL, clear the respective list
4059 vertstrings_count = 0;
4060 if (!geometrystring)
4061 geomstrings_count = 0;
4062 if (!fragmentstring)
4063 fragstrings_count = 0;
4065 vertstring_length = 0;
4066 for (i = 0;i < vertstrings_count;i++)
4067 vertstring_length += strlen(vertstrings_list[i]);
4068 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4069 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4070 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4072 geomstring_length = 0;
4073 for (i = 0;i < geomstrings_count;i++)
4074 geomstring_length += strlen(geomstrings_list[i]);
4075 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4076 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4077 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4079 fragstring_length = 0;
4080 for (i = 0;i < fragstrings_count;i++)
4081 fragstring_length += strlen(fragstrings_list[i]);
4082 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4083 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4084 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4088 //vertexProfile = CG_PROFILE_ARBVP1;
4089 //fragmentProfile = CG_PROFILE_ARBFP1;
4090 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4091 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4092 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4093 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4094 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4097 // try to load the cached shader, or generate one
4098 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4100 // if caching failed, do a dynamic compile for now
4102 if (vertstring[0] && !p->vprogram)
4103 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4105 if (fragstring[0] && !p->fprogram)
4106 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4109 // look up all the uniform variable names we care about, so we don't
4110 // have to look them up every time we set them
4114 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4115 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4116 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4117 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4118 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4119 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4120 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4121 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4122 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4123 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4124 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4125 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4131 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4132 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4133 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4134 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4135 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4136 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4137 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4138 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4139 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4140 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4141 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4142 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4143 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4144 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4145 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4146 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4147 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4148 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4149 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4150 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4151 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4152 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4153 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4154 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4155 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4156 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4157 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4158 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4159 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4160 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4161 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4162 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4163 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4164 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4165 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4166 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4167 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4168 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4169 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4170 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4171 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4172 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4173 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4174 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4175 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4176 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4177 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4178 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4179 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4180 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4181 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4182 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4183 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4184 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4185 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4186 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4187 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4188 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4189 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4190 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4191 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4192 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4193 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4194 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4195 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4196 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4197 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4198 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4199 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4200 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4201 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4202 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4203 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4204 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4205 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4206 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4207 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4211 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4212 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4214 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4218 Mem_Free(vertstring);
4220 Mem_Free(geomstring);
4222 Mem_Free(fragstring);
4224 Mem_Free(vertexstring);
4226 Mem_Free(geometrystring);
4228 Mem_Free(fragmentstring);
4231 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4233 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4236 if (r_cg_permutation != perm)
4238 r_cg_permutation = perm;
4239 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4241 if (!r_cg_permutation->compiled)
4242 R_CG_CompilePermutation(perm, mode, permutation);
4243 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4245 // remove features until we find a valid permutation
4247 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4249 // reduce i more quickly whenever it would not remove any bits
4250 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4251 if (!(permutation & j))
4254 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4255 if (!r_cg_permutation->compiled)
4256 R_CG_CompilePermutation(perm, mode, permutation);
4257 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4260 if (i >= SHADERPERMUTATION_COUNT)
4262 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4263 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4264 return; // no bit left to clear, entire mode is broken
4270 if (r_cg_permutation->vprogram)
4272 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4273 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4274 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4278 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4279 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4281 if (r_cg_permutation->fprogram)
4283 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4284 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4285 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4289 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4290 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4294 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4295 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4296 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4299 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4301 cgGLSetTextureParameter(param, R_GetTexture(tex));
4302 cgGLEnableTextureParameter(param);
4310 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4311 extern D3DCAPS9 vid_d3d9caps;
4314 struct r_hlsl_permutation_s;
4315 typedef struct r_hlsl_permutation_s
4317 /// hash lookup data
4318 struct r_hlsl_permutation_s *hashnext;
4320 unsigned int permutation;
4322 /// indicates if we have tried compiling this permutation already
4324 /// NULL if compilation failed
4325 IDirect3DVertexShader9 *vertexshader;
4326 IDirect3DPixelShader9 *pixelshader;
4328 r_hlsl_permutation_t;
4330 typedef enum D3DVSREGISTER_e
4332 D3DVSREGISTER_TexMatrix = 0, // float4x4
4333 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4334 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4335 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4336 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4337 D3DVSREGISTER_ModelToLight = 20, // float4x4
4338 D3DVSREGISTER_EyePosition = 24,
4339 D3DVSREGISTER_FogPlane = 25,
4340 D3DVSREGISTER_LightDir = 26,
4341 D3DVSREGISTER_LightPosition = 27,
4345 typedef enum D3DPSREGISTER_e
4347 D3DPSREGISTER_Alpha = 0,
4348 D3DPSREGISTER_BloomBlur_Parameters = 1,
4349 D3DPSREGISTER_ClientTime = 2,
4350 D3DPSREGISTER_Color_Ambient = 3,
4351 D3DPSREGISTER_Color_Diffuse = 4,
4352 D3DPSREGISTER_Color_Specular = 5,
4353 D3DPSREGISTER_Color_Glow = 6,
4354 D3DPSREGISTER_Color_Pants = 7,
4355 D3DPSREGISTER_Color_Shirt = 8,
4356 D3DPSREGISTER_DeferredColor_Ambient = 9,
4357 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4358 D3DPSREGISTER_DeferredColor_Specular = 11,
4359 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4360 D3DPSREGISTER_DeferredMod_Specular = 13,
4361 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4362 D3DPSREGISTER_EyePosition = 15, // unused
4363 D3DPSREGISTER_FogColor = 16,
4364 D3DPSREGISTER_FogHeightFade = 17,
4365 D3DPSREGISTER_FogPlane = 18,
4366 D3DPSREGISTER_FogPlaneViewDist = 19,
4367 D3DPSREGISTER_FogRangeRecip = 20,
4368 D3DPSREGISTER_LightColor = 21,
4369 D3DPSREGISTER_LightDir = 22, // unused
4370 D3DPSREGISTER_LightPosition = 23,
4371 D3DPSREGISTER_OffsetMapping_Scale = 24,
4372 D3DPSREGISTER_PixelSize = 25,
4373 D3DPSREGISTER_ReflectColor = 26,
4374 D3DPSREGISTER_ReflectFactor = 27,
4375 D3DPSREGISTER_ReflectOffset = 28,
4376 D3DPSREGISTER_RefractColor = 29,
4377 D3DPSREGISTER_Saturation = 30,
4378 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4379 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4380 D3DPSREGISTER_ScreenToDepth = 33,
4381 D3DPSREGISTER_ShadowMap_Parameters = 34,
4382 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4383 D3DPSREGISTER_SpecularPower = 36,
4384 D3DPSREGISTER_UserVec1 = 37,
4385 D3DPSREGISTER_UserVec2 = 38,
4386 D3DPSREGISTER_UserVec3 = 39,
4387 D3DPSREGISTER_UserVec4 = 40,
4388 D3DPSREGISTER_ViewTintColor = 41,
4389 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4390 D3DPSREGISTER_BloomColorSubtract = 43,
4391 D3DPSREGISTER_ViewToLight = 44, // float4x4
4392 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4397 /// information about each possible shader permutation
4398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4399 /// currently selected permutation
4400 r_hlsl_permutation_t *r_hlsl_permutation;
4401 /// storage for permutations linked in the hash table
4402 memexpandablearray_t r_hlsl_permutationarray;
4404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4406 //unsigned int hashdepth = 0;
4407 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4408 r_hlsl_permutation_t *p;
4409 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4411 if (p->mode == mode && p->permutation == permutation)
4413 //if (hashdepth > 10)
4414 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4419 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4421 p->permutation = permutation;
4422 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4423 r_hlsl_permutationhash[mode][hashindex] = p;
4424 //if (hashdepth > 10)
4425 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4432 if (!filename || !filename[0])
4434 if (!strcmp(filename, "hlsl/default.hlsl"))
4436 if (!hlslshaderstring)
4438 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4439 if (hlslshaderstring)
4440 Con_DPrintf("Loading shaders from file %s...\n", filename);
4442 hlslshaderstring = (char *)builtincgshaderstring;
4444 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4445 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4446 return shaderstring;
4448 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4451 if (printfromdisknotice)
4452 Con_DPrintf("from disk %s... ", filename);
4453 return shaderstring;
4455 return shaderstring;
4459 //#include <d3dx9shader.h>
4460 //#include <d3dx9mesh.h>
4462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4464 DWORD *vsbin = NULL;
4465 DWORD *psbin = NULL;
4466 fs_offset_t vsbinsize;
4467 fs_offset_t psbinsize;
4468 // IDirect3DVertexShader9 *vs = NULL;
4469 // IDirect3DPixelShader9 *ps = NULL;
4470 ID3DXBuffer *vslog = NULL;
4471 ID3DXBuffer *vsbuffer = NULL;
4472 ID3DXConstantTable *vsconstanttable = NULL;
4473 ID3DXBuffer *pslog = NULL;
4474 ID3DXBuffer *psbuffer = NULL;
4475 ID3DXConstantTable *psconstanttable = NULL;
4478 char temp[MAX_INPUTLINE];
4479 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4480 qboolean debugshader = gl_paranoid.integer != 0;
4481 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4482 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4485 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4486 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4488 if (debugshader || (!vsbin && vertstring) || (!psbin && fragstring))
4490 const char* dllnames_d3dx9 [] =
4514 dllhandle_t d3dx9_dll = NULL;
4515 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4516 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4517 dllfunction_t d3dx9_dllfuncs[] =
4519 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4520 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4523 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4525 DWORD shaderflags = 0;
4527 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4528 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4529 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4530 if (vertstring && vertstring[0])
4534 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4535 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4538 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4541 vsbinsize = vsbuffer->GetBufferSize();
4542 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4543 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4544 vsbuffer->Release();
4548 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4549 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4553 if (fragstring && fragstring[0])
4557 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4558 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4561 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4564 psbinsize = psbuffer->GetBufferSize();
4565 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4566 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4567 psbuffer->Release();
4571 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4572 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4576 Sys_UnloadLibrary(&d3dx9_dll);
4579 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4583 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4584 if (FAILED(vsresult))
4585 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4589 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4590 if (FAILED(psresult))
4591 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4593 // free the shader data
4594 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4595 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4598 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4601 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4602 int vertstrings_count = 0, vertstring_length = 0;
4603 int geomstrings_count = 0, geomstring_length = 0;
4604 int fragstrings_count = 0, fragstring_length = 0;
4606 char *vertexstring, *geometrystring, *fragmentstring;
4607 char *vertstring, *geomstring, *fragstring;
4608 const char *vertstrings_list[32+3];
4609 const char *geomstrings_list[32+3];
4610 const char *fragstrings_list[32+3];
4611 char permutationname[256];
4612 char cachename[256];
4617 p->vertexshader = NULL;
4618 p->pixelshader = NULL;
4620 permutationname[0] = 0;
4622 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4623 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4624 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4626 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4627 strlcat(cachename, "hlsl/", sizeof(cachename));
4629 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4630 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4631 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4632 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4634 // the first pretext is which type of shader to compile as
4635 // (later these will all be bound together as a program object)
4636 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4637 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4638 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4640 // the second pretext is the mode (for example a light source)
4641 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4642 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4643 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4644 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4645 strlcat(cachename, modeinfo->name, sizeof(cachename));
4647 // now add all the permutation pretexts
4648 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4650 if (permutation & (1<<i))
4652 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4653 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4654 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4655 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4656 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4660 // keep line numbers correct
4661 vertstrings_list[vertstrings_count++] = "\n";
4662 geomstrings_list[geomstrings_count++] = "\n";
4663 fragstrings_list[fragstrings_count++] = "\n";
4667 // replace spaces in the cachename with _ characters
4668 for (i = 0;cachename[i];i++)
4669 if (cachename[i] == ' ')
4672 // now append the shader text itself
4673 vertstrings_list[vertstrings_count++] = vertexstring;
4674 geomstrings_list[geomstrings_count++] = geometrystring;
4675 fragstrings_list[fragstrings_count++] = fragmentstring;
4677 // if any sources were NULL, clear the respective list
4679 vertstrings_count = 0;
4680 if (!geometrystring)
4681 geomstrings_count = 0;
4682 if (!fragmentstring)
4683 fragstrings_count = 0;
4685 vertstring_length = 0;
4686 for (i = 0;i < vertstrings_count;i++)
4687 vertstring_length += strlen(vertstrings_list[i]);
4688 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4689 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4690 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4692 geomstring_length = 0;
4693 for (i = 0;i < geomstrings_count;i++)
4694 geomstring_length += strlen(geomstrings_list[i]);
4695 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4696 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4697 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4699 fragstring_length = 0;
4700 for (i = 0;i < fragstrings_count;i++)
4701 fragstring_length += strlen(fragstrings_list[i]);
4702 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4703 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4704 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4706 // try to load the cached shader, or generate one
4707 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4709 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4710 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4712 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4716 Mem_Free(vertstring);
4718 Mem_Free(geomstring);
4720 Mem_Free(fragstring);
4722 Mem_Free(vertexstring);
4724 Mem_Free(geometrystring);
4726 Mem_Free(fragmentstring);
4729 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4730 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4731 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);}
4732 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);}
4733 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);}
4734 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);}
4736 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4737 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4738 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);}
4739 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);}
4740 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);}
4741 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);}
4743 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4745 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4746 if (r_hlsl_permutation != perm)
4748 r_hlsl_permutation = perm;
4749 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4751 if (!r_hlsl_permutation->compiled)
4752 R_HLSL_CompilePermutation(perm, mode, permutation);
4753 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4755 // remove features until we find a valid permutation
4757 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4759 // reduce i more quickly whenever it would not remove any bits
4760 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4761 if (!(permutation & j))
4764 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4765 if (!r_hlsl_permutation->compiled)
4766 R_HLSL_CompilePermutation(perm, mode, permutation);
4767 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4770 if (i >= SHADERPERMUTATION_COUNT)
4772 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4773 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4774 return; // no bit left to clear, entire mode is broken
4778 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4779 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4781 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4782 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4783 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4787 void R_GLSL_Restart_f(void)
4789 unsigned int i, limit;
4790 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4791 Mem_Free(glslshaderstring);
4792 glslshaderstring = NULL;
4793 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4794 Mem_Free(cgshaderstring);
4795 cgshaderstring = NULL;
4796 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4797 Mem_Free(hlslshaderstring);
4798 hlslshaderstring = NULL;
4799 switch(vid.renderpath)
4801 case RENDERPATH_D3D9:
4804 r_hlsl_permutation_t *p;
4805 r_hlsl_permutation = NULL;
4806 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4807 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4808 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4809 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4810 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4811 for (i = 0;i < limit;i++)
4813 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4815 if (p->vertexshader)
4816 IDirect3DVertexShader9_Release(p->vertexshader);
4818 IDirect3DPixelShader9_Release(p->pixelshader);
4819 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4822 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4826 case RENDERPATH_D3D10:
4827 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4829 case RENDERPATH_D3D11:
4830 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4832 case RENDERPATH_GL20:
4834 r_glsl_permutation_t *p;
4835 r_glsl_permutation = NULL;
4836 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4837 for (i = 0;i < limit;i++)
4839 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4841 GL_Backend_FreeProgram(p->program);
4842 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4845 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4848 case RENDERPATH_CGGL:
4851 r_cg_permutation_t *p;
4852 r_cg_permutation = NULL;
4853 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4854 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4855 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4856 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4857 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4858 for (i = 0;i < limit;i++)
4860 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4863 cgDestroyProgram(p->vprogram);
4865 cgDestroyProgram(p->fprogram);
4866 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4869 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4873 case RENDERPATH_GL13:
4874 case RENDERPATH_GL11:
4879 void R_GLSL_DumpShader_f(void)
4884 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4887 FS_Print(file, "/* The engine may define the following macros:\n");
4888 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4889 for (i = 0;i < SHADERMODE_COUNT;i++)
4890 FS_Print(file, glslshadermodeinfo[i].pretext);
4891 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4892 FS_Print(file, shaderpermutationinfo[i].pretext);
4893 FS_Print(file, "*/\n");
4894 FS_Print(file, builtinshaderstring);
4896 Con_Printf("glsl/default.glsl written\n");
4899 Con_Printf("failed to write to glsl/default.glsl\n");
4902 file = FS_OpenRealFile("cg/default.cg", "w", false);
4905 FS_Print(file, "/* The engine may define the following macros:\n");
4906 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4907 for (i = 0;i < SHADERMODE_COUNT;i++)
4908 FS_Print(file, cgshadermodeinfo[i].pretext);
4909 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4910 FS_Print(file, shaderpermutationinfo[i].pretext);
4911 FS_Print(file, "*/\n");
4912 FS_Print(file, builtincgshaderstring);
4914 Con_Printf("cg/default.cg written\n");
4917 Con_Printf("failed to write to cg/default.cg\n");
4921 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4924 FS_Print(file, "/* The engine may define the following macros:\n");
4925 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4926 for (i = 0;i < SHADERMODE_COUNT;i++)
4927 FS_Print(file, hlslshadermodeinfo[i].pretext);
4928 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4929 FS_Print(file, shaderpermutationinfo[i].pretext);
4930 FS_Print(file, "*/\n");
4931 FS_Print(file, builtincgshaderstring);
4933 Con_Printf("hlsl/default.hlsl written\n");
4936 Con_Printf("failed to write to hlsl/default.hlsl\n");
4940 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4943 texturemode = GL_MODULATE;
4944 switch (vid.renderpath)
4946 case RENDERPATH_D3D9:
4948 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))));
4949 R_Mesh_TexBind(GL20TU_FIRST , first );
4950 R_Mesh_TexBind(GL20TU_SECOND, second);
4953 case RENDERPATH_D3D10:
4954 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4956 case RENDERPATH_D3D11:
4957 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4959 case RENDERPATH_GL20:
4960 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))));
4961 R_Mesh_TexBind(GL20TU_FIRST , first );
4962 R_Mesh_TexBind(GL20TU_SECOND, second);
4964 case RENDERPATH_CGGL:
4967 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))));
4968 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4969 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4972 case RENDERPATH_GL13:
4973 R_Mesh_TexBind(0, first );
4974 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4975 R_Mesh_TexBind(1, second);
4977 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4979 case RENDERPATH_GL11:
4980 R_Mesh_TexBind(0, first );
4985 void R_SetupShader_DepthOrShadow(void)
4987 switch (vid.renderpath)
4989 case RENDERPATH_D3D9:
4991 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4994 case RENDERPATH_D3D10:
4995 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4997 case RENDERPATH_D3D11:
4998 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5000 case RENDERPATH_GL20:
5001 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5003 case RENDERPATH_CGGL:
5005 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5008 case RENDERPATH_GL13:
5009 R_Mesh_TexBind(0, 0);
5010 R_Mesh_TexBind(1, 0);
5012 case RENDERPATH_GL11:
5013 R_Mesh_TexBind(0, 0);
5018 void R_SetupShader_ShowDepth(void)
5020 switch (vid.renderpath)
5022 case RENDERPATH_D3D9:
5024 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5027 case RENDERPATH_D3D10:
5028 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5030 case RENDERPATH_D3D11:
5031 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5033 case RENDERPATH_GL20:
5034 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5036 case RENDERPATH_CGGL:
5038 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5041 case RENDERPATH_GL13:
5043 case RENDERPATH_GL11:
5048 extern qboolean r_shadow_usingdeferredprepass;
5049 extern cvar_t r_shadow_deferred_8bitrange;
5050 extern rtexture_t *r_shadow_attenuationgradienttexture;
5051 extern rtexture_t *r_shadow_attenuation2dtexture;
5052 extern rtexture_t *r_shadow_attenuation3dtexture;
5053 extern qboolean r_shadow_usingshadowmap2d;
5054 extern qboolean r_shadow_usingshadowmaportho;
5055 extern float r_shadow_shadowmap_texturescale[2];
5056 extern float r_shadow_shadowmap_parameters[4];
5057 extern qboolean r_shadow_shadowmapvsdct;
5058 extern qboolean r_shadow_shadowmapsampler;
5059 extern int r_shadow_shadowmappcf;
5060 extern rtexture_t *r_shadow_shadowmap2dtexture;
5061 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5062 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5063 extern matrix4x4_t r_shadow_shadowmapmatrix;
5064 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5065 extern int r_shadow_prepass_width;
5066 extern int r_shadow_prepass_height;
5067 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5068 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5069 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5070 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5071 extern cvar_t gl_mesh_separatearrays;
5072 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5074 // a blendfunc allows colormod if:
5075 // a) it can never keep the destination pixel invariant, or
5076 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5077 // this is to prevent unintended side effects from colormod
5080 // IF there is a (s, sa) for which for all (d, da),
5081 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5082 // THEN, for this (s, sa) and all (colormod, d, da):
5083 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5084 // OBVIOUSLY, this means that
5085 // s*colormod * src(s*colormod, d, sa, da) = 0
5086 // dst(s*colormod, d, sa, da) = 1
5088 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5090 // main condition to leave dst color invariant:
5091 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5093 // s * 0 + d * dst(s, d, sa, da) == d
5094 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5095 // => colormod is a problem for GL_SRC_COLOR only
5097 // s + d * dst(s, d, sa, da) == d
5099 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5100 // => colormod is never problematic for these
5101 // src == GL_SRC_COLOR:
5102 // s*s + d * dst(s, d, sa, da) == d
5104 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5105 // => colormod is never problematic for these
5106 // src == GL_ONE_MINUS_SRC_COLOR:
5107 // s*(1-s) + d * dst(s, d, sa, da) == d
5108 // => s == 0 or s == 1
5109 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5110 // => colormod is a problem for GL_SRC_COLOR only
5111 // src == GL_DST_COLOR
5112 // s*d + d * dst(s, d, sa, da) == d
5114 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5115 // => colormod is always a problem
5118 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5119 // => colormod is never problematic for these
5120 // => BUT, we do not know s! We must assume it is problematic
5121 // then... except in GL_ONE case, where we know all invariant
5123 // src == GL_ONE_MINUS_DST_COLOR
5124 // s*(1-d) + d * dst(s, d, sa, da) == d
5125 // => s == 0 (1-d is impossible to handle for our desired result)
5126 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5127 // => colormod is never problematic for these
5128 // src == GL_SRC_ALPHA
5129 // s*sa + d * dst(s, d, sa, da) == d
5130 // => s == 0, or sa == 0
5131 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5132 // => colormod breaks in the case GL_SRC_COLOR only
5133 // src == GL_ONE_MINUS_SRC_ALPHA
5134 // s*(1-sa) + d * dst(s, d, sa, da) == d
5135 // => s == 0, or sa == 1
5136 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5137 // => colormod breaks in the case GL_SRC_COLOR only
5138 // src == GL_DST_ALPHA
5139 // s*da + d * dst(s, d, sa, da) == d
5141 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5142 // => colormod is never problematic for these
5147 case GL_ONE_MINUS_SRC_COLOR:
5149 case GL_ONE_MINUS_SRC_ALPHA:
5150 if(dst == GL_SRC_COLOR)
5155 case GL_ONE_MINUS_DST_COLOR:
5157 case GL_ONE_MINUS_DST_ALPHA:
5167 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)
5169 // select a permutation of the lighting shader appropriate to this
5170 // combination of texture, entity, light source, and fogging, only use the
5171 // minimum features necessary to avoid wasting rendering time in the
5172 // fragment shader on features that are not being used
5173 unsigned int permutation = 0;
5174 unsigned int mode = 0;
5175 qboolean allow_colormod;
5176 static float dummy_colormod[3] = {1, 1, 1};
5177 float *colormod = rsurface.colormod;
5179 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5180 if (rsurfacepass == RSURFPASS_BACKGROUND)
5182 // distorted background
5183 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5184 mode = SHADERMODE_WATER;
5185 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5186 mode = SHADERMODE_REFRACTION;
5189 mode = SHADERMODE_GENERIC;
5190 permutation |= SHADERPERMUTATION_DIFFUSE;
5192 GL_AlphaTest(false);
5193 GL_BlendFunc(GL_ONE, GL_ZERO);
5194 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5196 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5198 if (r_glsl_offsetmapping.integer)
5200 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5201 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5202 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5203 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5204 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5206 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5207 if (r_glsl_offsetmapping_reliefmapping.integer)
5208 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5212 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5214 permutation |= SHADERPERMUTATION_ALPHAKILL;
5215 // normalmap (deferred prepass), may use alpha test on diffuse
5216 mode = SHADERMODE_DEFERREDGEOMETRY;
5217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5218 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5219 GL_AlphaTest(false);
5220 GL_BlendFunc(GL_ONE, GL_ZERO);
5221 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5223 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5225 if (r_glsl_offsetmapping.integer)
5227 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5228 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5229 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5230 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5231 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5233 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5234 if (r_glsl_offsetmapping_reliefmapping.integer)
5235 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5238 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5239 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5241 mode = SHADERMODE_LIGHTSOURCE;
5242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5243 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5244 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5245 permutation |= SHADERPERMUTATION_CUBEFILTER;
5246 if (diffusescale > 0)
5247 permutation |= SHADERPERMUTATION_DIFFUSE;
5248 if (specularscale > 0)
5250 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5251 if (r_shadow_glossexact.integer)
5252 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5254 if (r_refdef.fogenabled)
5255 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5256 if (rsurface.texture->colormapping)
5257 permutation |= SHADERPERMUTATION_COLORMAPPING;
5258 if (r_shadow_usingshadowmap2d)
5260 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5261 if(r_shadow_shadowmapvsdct)
5262 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5264 if (r_shadow_shadowmapsampler)
5265 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5266 if (r_shadow_shadowmappcf > 1)
5267 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5268 else if (r_shadow_shadowmappcf)
5269 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5271 if (rsurface.texture->reflectmasktexture)
5272 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5273 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5274 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5275 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5277 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5279 if (r_glsl_offsetmapping.integer)
5281 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5282 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5283 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5284 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5285 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5287 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5288 if (r_glsl_offsetmapping_reliefmapping.integer)
5289 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5293 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5294 // unshaded geometry (fullbright or ambient model lighting)
5295 mode = SHADERMODE_FLATCOLOR;
5296 ambientscale = diffusescale = specularscale = 0;
5297 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5298 permutation |= SHADERPERMUTATION_GLOW;
5299 if (r_refdef.fogenabled)
5300 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5301 if (rsurface.texture->colormapping)
5302 permutation |= SHADERPERMUTATION_COLORMAPPING;
5303 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5305 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5306 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5308 if (r_shadow_shadowmapsampler)
5309 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5310 if (r_shadow_shadowmappcf > 1)
5311 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5312 else if (r_shadow_shadowmappcf)
5313 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5315 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5316 permutation |= SHADERPERMUTATION_REFLECTION;
5317 if (rsurface.texture->reflectmasktexture)
5318 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5319 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5320 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5321 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5323 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5325 if (r_glsl_offsetmapping.integer)
5327 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5328 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5329 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5330 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5331 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5333 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5334 if (r_glsl_offsetmapping_reliefmapping.integer)
5335 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5338 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5339 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5340 // directional model lighting
5341 mode = SHADERMODE_LIGHTDIRECTION;
5342 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5343 permutation |= SHADERPERMUTATION_GLOW;
5344 permutation |= SHADERPERMUTATION_DIFFUSE;
5345 if (specularscale > 0)
5347 permutation |= SHADERPERMUTATION_SPECULAR;
5348 if (r_shadow_glossexact.integer)
5349 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5351 if (r_refdef.fogenabled)
5352 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5353 if (rsurface.texture->colormapping)
5354 permutation |= SHADERPERMUTATION_COLORMAPPING;
5355 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5357 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5358 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5360 if (r_shadow_shadowmapsampler)
5361 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5362 if (r_shadow_shadowmappcf > 1)
5363 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5364 else if (r_shadow_shadowmappcf)
5365 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5368 permutation |= SHADERPERMUTATION_REFLECTION;
5369 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5370 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5371 if (rsurface.texture->reflectmasktexture)
5372 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5373 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5374 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5375 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5377 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5379 if (r_glsl_offsetmapping.integer)
5381 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5382 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5383 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5384 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5385 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5387 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5388 if (r_glsl_offsetmapping_reliefmapping.integer)
5389 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5392 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5393 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5394 // ambient model lighting
5395 mode = SHADERMODE_LIGHTDIRECTION;
5396 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5397 permutation |= SHADERPERMUTATION_GLOW;
5398 if (r_refdef.fogenabled)
5399 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5400 if (rsurface.texture->colormapping)
5401 permutation |= SHADERPERMUTATION_COLORMAPPING;
5402 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5404 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5405 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5407 if (r_shadow_shadowmapsampler)
5408 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5409 if (r_shadow_shadowmappcf > 1)
5410 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5411 else if (r_shadow_shadowmappcf)
5412 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5414 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5415 permutation |= SHADERPERMUTATION_REFLECTION;
5416 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5417 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5418 if (rsurface.texture->reflectmasktexture)
5419 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5420 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5421 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5422 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5426 if (r_glsl_offsetmapping.integer)
5428 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5429 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5430 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5431 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5432 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5434 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5435 if (r_glsl_offsetmapping_reliefmapping.integer)
5436 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5439 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5440 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5442 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5443 permutation |= SHADERPERMUTATION_GLOW;
5444 if (r_refdef.fogenabled)
5445 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5446 if (rsurface.texture->colormapping)
5447 permutation |= SHADERPERMUTATION_COLORMAPPING;
5448 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5450 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5451 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5453 if (r_shadow_shadowmapsampler)
5454 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5455 if (r_shadow_shadowmappcf > 1)
5456 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5457 else if (r_shadow_shadowmappcf)
5458 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5461 permutation |= SHADERPERMUTATION_REFLECTION;
5462 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5463 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5464 if (rsurface.texture->reflectmasktexture)
5465 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5466 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5468 // deluxemapping (light direction texture)
5469 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5470 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5472 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5473 permutation |= SHADERPERMUTATION_DIFFUSE;
5474 if (specularscale > 0)
5476 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5477 if (r_shadow_glossexact.integer)
5478 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5481 else if (r_glsl_deluxemapping.integer >= 2)
5483 // fake deluxemapping (uniform light direction in tangentspace)
5484 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5485 permutation |= SHADERPERMUTATION_DIFFUSE;
5486 if (specularscale > 0)
5488 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5489 if (r_shadow_glossexact.integer)
5490 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5493 else if (rsurface.uselightmaptexture)
5495 // ordinary lightmapping (q1bsp, q3bsp)
5496 mode = SHADERMODE_LIGHTMAP;
5500 // ordinary vertex coloring (q3bsp)
5501 mode = SHADERMODE_VERTEXCOLOR;
5503 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5504 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5505 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5508 colormod = dummy_colormod;
5509 switch(vid.renderpath)
5511 case RENDERPATH_D3D9:
5513 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);
5514 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5515 R_SetupShader_SetPermutationHLSL(mode, permutation);
5516 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5517 if (mode == SHADERMODE_LIGHTSOURCE)
5519 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5520 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5524 if (mode == SHADERMODE_LIGHTDIRECTION)
5526 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5529 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5530 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5531 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5532 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5533 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5535 if (mode == SHADERMODE_LIGHTSOURCE)
5537 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5538 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5539 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5540 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5541 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5543 // additive passes are only darkened by fog, not tinted
5544 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5545 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5549 if (mode == SHADERMODE_FLATCOLOR)
5551 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5553 else if (mode == SHADERMODE_LIGHTDIRECTION)
5555 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]);
5556 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5557 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);
5558 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);
5559 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5560 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5561 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5565 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5566 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5567 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);
5568 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);
5569 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5571 // additive passes are only darkened by fog, not tinted
5572 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5573 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5575 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5576 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);
5577 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5578 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5579 hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5580 hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5581 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5582 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5583 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5585 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5586 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5587 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5588 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5589 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5590 if (rsurface.texture->pantstexture)
5591 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5594 if (rsurface.texture->shirttexture)
5595 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5597 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5598 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5599 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5600 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5601 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5602 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5603 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5604 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5606 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5607 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5608 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5609 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5610 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5611 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5612 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5613 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5614 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5615 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5616 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5617 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5618 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5619 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5620 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5621 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5622 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5623 if (rsurfacepass == RSURFPASS_BACKGROUND)
5625 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5626 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5627 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5631 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5633 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5634 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5635 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5636 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5637 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5639 R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5640 if (rsurface.rtlight)
5642 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5643 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5648 case RENDERPATH_D3D10:
5649 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5651 case RENDERPATH_D3D11:
5652 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5654 case RENDERPATH_GL20:
5655 if (gl_mesh_separatearrays.integer)
5657 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);
5658 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5659 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5660 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5661 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5662 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5663 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5664 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5668 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);
5669 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5671 R_SetupShader_SetPermutationGLSL(mode, permutation);
5672 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5673 if (mode == SHADERMODE_LIGHTSOURCE)
5675 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5676 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5677 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5678 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5679 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5680 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);
5682 // additive passes are only darkened by fog, not tinted
5683 if (r_glsl_permutation->loc_FogColor >= 0)
5684 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5685 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5689 if (mode == SHADERMODE_FLATCOLOR)
5691 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5693 else if (mode == SHADERMODE_LIGHTDIRECTION)
5695 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]);
5696 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]);
5697 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);
5698 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);
5699 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);
5700 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]);
5701 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]);
5705 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]);
5706 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]);
5707 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);
5708 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);
5709 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);
5711 // additive passes are only darkened by fog, not tinted
5712 if (r_glsl_permutation->loc_FogColor >= 0)
5714 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5715 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5717 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5719 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);
5720 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]);
5721 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]);
5722 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5723 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5724 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5725 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5726 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5728 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5729 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5730 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5731 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]);
5732 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]);
5734 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5735 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5736 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5737 if (r_glsl_permutation->loc_Color_Pants >= 0)
5739 if (rsurface.texture->pantstexture)
5740 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5742 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5744 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5746 if (rsurface.texture->shirttexture)
5747 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5749 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5751 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]);
5752 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5753 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5754 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5755 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5756 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]);
5757 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5759 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5760 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5761 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5762 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5763 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5764 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5765 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5766 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5767 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5768 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5769 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5770 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5771 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5772 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5773 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5774 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5775 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5776 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5777 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5778 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5779 if (rsurfacepass == RSURFPASS_BACKGROUND)
5781 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5782 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5783 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5787 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5789 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5790 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5791 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5792 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5793 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5795 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5796 if (rsurface.rtlight)
5798 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5799 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5804 case RENDERPATH_CGGL:
5806 if (gl_mesh_separatearrays.integer)
5808 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);
5809 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5810 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5811 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5812 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5813 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5814 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5815 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5819 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);
5820 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5822 R_SetupShader_SetPermutationCG(mode, permutation);
5823 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5824 if (mode == SHADERMODE_LIGHTSOURCE)
5826 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5827 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5831 if (mode == SHADERMODE_LIGHTDIRECTION)
5833 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
5836 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5837 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5838 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5839 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5840 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
5843 if (mode == SHADERMODE_LIGHTSOURCE)
5845 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5846 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5847 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5848 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5849 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
5851 // additive passes are only darkened by fog, not tinted
5852 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5853 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5857 if (mode == SHADERMODE_FLATCOLOR)
5859 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5861 else if (mode == SHADERMODE_LIGHTDIRECTION)
5863 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
5864 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
5865 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
5866 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
5867 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
5868 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
5869 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
5873 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
5874 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
5875 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
5876 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
5877 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
5879 // additive passes are only darkened by fog, not tinted
5880 if (r_cg_permutation->fp_FogColor)
5882 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5883 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5885 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5888 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
5889 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
5890 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
5891 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5892 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5893 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5894 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5895 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5897 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
5898 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
5899 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5900 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5901 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5902 if (r_cg_permutation->fp_Color_Pants)
5904 if (rsurface.texture->pantstexture)
5905 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5907 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5910 if (r_cg_permutation->fp_Color_Shirt)
5912 if (rsurface.texture->shirttexture)
5913 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5915 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5918 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
5919 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5920 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5921 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5922 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5923 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
5924 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5926 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
5927 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
5928 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
5929 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
5930 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
5931 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
5932 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
5933 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
5934 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
5935 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
5936 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
5937 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
5938 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
5939 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
5940 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
5941 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
5942 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
5943 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5944 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5945 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
5946 if (rsurfacepass == RSURFPASS_BACKGROUND)
5948 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
5949 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
5950 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
5954 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
5956 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
5957 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
5958 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
5959 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
5960 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5962 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
5963 if (rsurface.rtlight)
5965 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
5966 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
5973 case RENDERPATH_GL13:
5974 case RENDERPATH_GL11:
5979 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5981 // select a permutation of the lighting shader appropriate to this
5982 // combination of texture, entity, light source, and fogging, only use the
5983 // minimum features necessary to avoid wasting rendering time in the
5984 // fragment shader on features that are not being used
5985 unsigned int permutation = 0;
5986 unsigned int mode = 0;
5987 const float *lightcolorbase = rtlight->currentcolor;
5988 float ambientscale = rtlight->ambientscale;
5989 float diffusescale = rtlight->diffusescale;
5990 float specularscale = rtlight->specularscale;
5991 // this is the location of the light in view space
5992 vec3_t viewlightorigin;
5993 // this transforms from view space (camera) to light space (cubemap)
5994 matrix4x4_t viewtolight;
5995 matrix4x4_t lighttoview;
5996 float viewtolight16f[16];
5997 float range = 1.0f / r_shadow_deferred_8bitrange.value;
5999 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6000 if (rtlight->currentcubemap != r_texture_whitecube)
6001 permutation |= SHADERPERMUTATION_CUBEFILTER;
6002 if (diffusescale > 0)
6003 permutation |= SHADERPERMUTATION_DIFFUSE;
6004 if (specularscale > 0)
6006 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6007 if (r_shadow_glossexact.integer)
6008 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6010 if (r_shadow_usingshadowmap2d)
6012 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6013 if (r_shadow_shadowmapvsdct)
6014 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6016 if (r_shadow_shadowmapsampler)
6017 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6018 if (r_shadow_shadowmappcf > 1)
6019 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6020 else if (r_shadow_shadowmappcf)
6021 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6023 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6024 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6025 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6026 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6027 switch(vid.renderpath)
6029 case RENDERPATH_D3D9:
6031 R_SetupShader_SetPermutationHLSL(mode, permutation);
6032 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6033 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6034 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6035 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6036 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6037 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6038 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6039 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6040 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6041 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6043 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6044 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6045 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6046 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6047 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6048 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6051 case RENDERPATH_D3D10:
6052 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6054 case RENDERPATH_D3D11:
6055 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6057 case RENDERPATH_GL20:
6058 R_SetupShader_SetPermutationGLSL(mode, permutation);
6059 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6060 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6061 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);
6062 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);
6063 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);
6064 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]);
6065 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]);
6066 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));
6067 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]);
6068 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6070 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6071 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6072 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6073 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6074 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6075 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6077 case RENDERPATH_CGGL:
6079 R_SetupShader_SetPermutationCG(mode, permutation);
6080 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6081 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6082 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
6083 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
6084 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
6085 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
6086 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
6087 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
6088 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
6089 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6091 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6092 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6093 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6094 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6095 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6096 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6099 case RENDERPATH_GL13:
6100 case RENDERPATH_GL11:
6105 #define SKINFRAME_HASH 1024
6109 int loadsequence; // incremented each level change
6110 memexpandablearray_t array;
6111 skinframe_t *hash[SKINFRAME_HASH];
6114 r_skinframe_t r_skinframe;
6116 void R_SkinFrame_PrepareForPurge(void)
6118 r_skinframe.loadsequence++;
6119 // wrap it without hitting zero
6120 if (r_skinframe.loadsequence >= 200)
6121 r_skinframe.loadsequence = 1;
6124 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6128 // mark the skinframe as used for the purging code
6129 skinframe->loadsequence = r_skinframe.loadsequence;
6132 void R_SkinFrame_Purge(void)
6136 for (i = 0;i < SKINFRAME_HASH;i++)
6138 for (s = r_skinframe.hash[i];s;s = s->next)
6140 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6142 if (s->merged == s->base)
6144 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6145 R_PurgeTexture(s->stain );s->stain = NULL;
6146 R_PurgeTexture(s->merged);s->merged = NULL;
6147 R_PurgeTexture(s->base );s->base = NULL;
6148 R_PurgeTexture(s->pants );s->pants = NULL;
6149 R_PurgeTexture(s->shirt );s->shirt = NULL;
6150 R_PurgeTexture(s->nmap );s->nmap = NULL;
6151 R_PurgeTexture(s->gloss );s->gloss = NULL;
6152 R_PurgeTexture(s->glow );s->glow = NULL;
6153 R_PurgeTexture(s->fog );s->fog = NULL;
6154 R_PurgeTexture(s->reflect);s->reflect = NULL;
6155 s->loadsequence = 0;
6161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6163 char basename[MAX_QPATH];
6165 Image_StripImageExtension(name, basename, sizeof(basename));
6167 if( last == NULL ) {
6169 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6170 item = r_skinframe.hash[hashindex];
6175 // linearly search through the hash bucket
6176 for( ; item ; item = item->next ) {
6177 if( !strcmp( item->basename, basename ) ) {
6184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6188 char basename[MAX_QPATH];
6190 Image_StripImageExtension(name, basename, sizeof(basename));
6192 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6193 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6194 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6198 rtexture_t *dyntexture;
6199 // check whether its a dynamic texture
6200 dyntexture = CL_GetDynTexture( basename );
6201 if (!add && !dyntexture)
6203 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6204 memset(item, 0, sizeof(*item));
6205 strlcpy(item->basename, basename, sizeof(item->basename));
6206 item->base = dyntexture; // either NULL or dyntexture handle
6207 item->textureflags = textureflags;
6208 item->comparewidth = comparewidth;
6209 item->compareheight = compareheight;
6210 item->comparecrc = comparecrc;
6211 item->next = r_skinframe.hash[hashindex];
6212 r_skinframe.hash[hashindex] = item;
6214 else if( item->base == NULL )
6216 rtexture_t *dyntexture;
6217 // check whether its a dynamic texture
6218 // 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]
6219 dyntexture = CL_GetDynTexture( basename );
6220 item->base = dyntexture; // either NULL or dyntexture handle
6223 R_SkinFrame_MarkUsed(item);
6227 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6229 unsigned long long avgcolor[5], wsum; \
6237 for(pix = 0; pix < cnt; ++pix) \
6240 for(comp = 0; comp < 3; ++comp) \
6242 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6245 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6247 for(comp = 0; comp < 3; ++comp) \
6248 avgcolor[comp] += getpixel * w; \
6251 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6252 avgcolor[4] += getpixel; \
6254 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6256 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6257 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6258 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6259 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6262 extern cvar_t gl_picmip;
6263 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6266 unsigned char *pixels;
6267 unsigned char *bumppixels;
6268 unsigned char *basepixels = NULL;
6269 int basepixels_width = 0;
6270 int basepixels_height = 0;
6271 skinframe_t *skinframe;
6272 rtexture_t *ddsbase = NULL;
6273 qboolean ddshasalpha = false;
6274 float ddsavgcolor[4];
6275 char basename[MAX_QPATH];
6276 int miplevel = R_PicmipForFlags(textureflags);
6277 int savemiplevel = miplevel;
6280 if (cls.state == ca_dedicated)
6283 // return an existing skinframe if already loaded
6284 // if loading of the first image fails, don't make a new skinframe as it
6285 // would cause all future lookups of this to be missing
6286 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6287 if (skinframe && skinframe->base)
6290 Image_StripImageExtension(name, basename, sizeof(basename));
6292 // check for DDS texture file first
6293 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6295 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6296 if (basepixels == NULL)
6300 // FIXME handle miplevel
6302 if (developer_loading.integer)
6303 Con_Printf("loading skin \"%s\"\n", name);
6305 // we've got some pixels to store, so really allocate this new texture now
6307 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6308 skinframe->stain = NULL;
6309 skinframe->merged = NULL;
6310 skinframe->base = NULL;
6311 skinframe->pants = NULL;
6312 skinframe->shirt = NULL;
6313 skinframe->nmap = NULL;
6314 skinframe->gloss = NULL;
6315 skinframe->glow = NULL;
6316 skinframe->fog = NULL;
6317 skinframe->reflect = NULL;
6318 skinframe->hasalpha = false;
6322 skinframe->base = ddsbase;
6323 skinframe->hasalpha = ddshasalpha;
6324 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6325 if (r_loadfog && skinframe->hasalpha)
6326 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6327 //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]);
6331 basepixels_width = image_width;
6332 basepixels_height = image_height;
6333 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);
6334 if (textureflags & TEXF_ALPHA)
6336 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6338 if (basepixels[j] < 255)
6340 skinframe->hasalpha = true;
6344 if (r_loadfog && skinframe->hasalpha)
6346 // has transparent pixels
6347 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6348 for (j = 0;j < image_width * image_height * 4;j += 4)
6353 pixels[j+3] = basepixels[j+3];
6355 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);
6359 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6360 //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]);
6361 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6362 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6363 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6364 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6369 mymiplevel = savemiplevel;
6370 if (r_loadnormalmap)
6371 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);
6372 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6374 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6375 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6376 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6377 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6380 // _norm is the name used by tenebrae and has been adopted as standard
6381 if (r_loadnormalmap && skinframe->nmap == NULL)
6383 mymiplevel = savemiplevel;
6384 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6386 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);
6390 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6392 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6393 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6394 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);
6396 Mem_Free(bumppixels);
6398 else if (r_shadow_bumpscale_basetexture.value > 0)
6400 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6401 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6402 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);
6405 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6406 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6409 // _luma is supported only for tenebrae compatibility
6410 // _glow is the preferred name
6411 mymiplevel = savemiplevel;
6412 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))))
6414 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);
6415 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6416 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6417 Mem_Free(pixels);pixels = NULL;
6420 mymiplevel = savemiplevel;
6421 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6423 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);
6424 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6425 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6430 mymiplevel = savemiplevel;
6431 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6433 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);
6434 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6435 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6440 mymiplevel = savemiplevel;
6441 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6443 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);
6444 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6445 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6450 mymiplevel = savemiplevel;
6451 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6453 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);
6454 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6455 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6461 Mem_Free(basepixels);
6466 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6467 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6470 unsigned char *temp1, *temp2;
6471 skinframe_t *skinframe;
6473 if (cls.state == ca_dedicated)
6476 // if already loaded just return it, otherwise make a new skinframe
6477 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6478 if (skinframe && skinframe->base)
6481 skinframe->stain = NULL;
6482 skinframe->merged = NULL;
6483 skinframe->base = NULL;
6484 skinframe->pants = NULL;
6485 skinframe->shirt = NULL;
6486 skinframe->nmap = NULL;
6487 skinframe->gloss = NULL;
6488 skinframe->glow = NULL;
6489 skinframe->fog = NULL;
6490 skinframe->reflect = NULL;
6491 skinframe->hasalpha = false;
6493 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6497 if (developer_loading.integer)
6498 Con_Printf("loading 32bit skin \"%s\"\n", name);
6500 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6502 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6503 temp2 = temp1 + width * height * 4;
6504 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6505 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);
6508 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6509 if (textureflags & TEXF_ALPHA)
6511 for (i = 3;i < width * height * 4;i += 4)
6513 if (skindata[i] < 255)
6515 skinframe->hasalpha = true;
6519 if (r_loadfog && skinframe->hasalpha)
6521 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6522 memcpy(fogpixels, skindata, width * height * 4);
6523 for (i = 0;i < width * height * 4;i += 4)
6524 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6525 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6526 Mem_Free(fogpixels);
6530 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6531 //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]);
6536 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6540 skinframe_t *skinframe;
6542 if (cls.state == ca_dedicated)
6545 // if already loaded just return it, otherwise make a new skinframe
6546 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6547 if (skinframe && skinframe->base)
6550 skinframe->stain = NULL;
6551 skinframe->merged = NULL;
6552 skinframe->base = NULL;
6553 skinframe->pants = NULL;
6554 skinframe->shirt = NULL;
6555 skinframe->nmap = NULL;
6556 skinframe->gloss = NULL;
6557 skinframe->glow = NULL;
6558 skinframe->fog = NULL;
6559 skinframe->reflect = NULL;
6560 skinframe->hasalpha = false;
6562 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6566 if (developer_loading.integer)
6567 Con_Printf("loading quake skin \"%s\"\n", name);
6569 // 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)
6570 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6571 memcpy(skinframe->qpixels, skindata, width*height);
6572 skinframe->qwidth = width;
6573 skinframe->qheight = height;
6576 for (i = 0;i < width * height;i++)
6577 featuresmask |= palette_featureflags[skindata[i]];
6579 skinframe->hasalpha = false;
6580 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6581 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6582 skinframe->qgeneratemerged = true;
6583 skinframe->qgeneratebase = skinframe->qhascolormapping;
6584 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6586 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6587 //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]);
6592 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6596 unsigned char *skindata;
6598 if (!skinframe->qpixels)
6601 if (!skinframe->qhascolormapping)
6602 colormapped = false;
6606 if (!skinframe->qgeneratebase)
6611 if (!skinframe->qgeneratemerged)
6615 width = skinframe->qwidth;
6616 height = skinframe->qheight;
6617 skindata = skinframe->qpixels;
6619 if (skinframe->qgeneratenmap)
6621 unsigned char *temp1, *temp2;
6622 skinframe->qgeneratenmap = false;
6623 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6624 temp2 = temp1 + width * height * 4;
6625 // use either a custom palette or the quake palette
6626 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6627 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6628 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);
6632 if (skinframe->qgenerateglow)
6634 skinframe->qgenerateglow = false;
6635 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6640 skinframe->qgeneratebase = false;
6641 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);
6642 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6643 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6647 skinframe->qgeneratemerged = false;
6648 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);
6651 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6653 Mem_Free(skinframe->qpixels);
6654 skinframe->qpixels = NULL;
6658 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)
6661 skinframe_t *skinframe;
6663 if (cls.state == ca_dedicated)
6666 // if already loaded just return it, otherwise make a new skinframe
6667 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6668 if (skinframe && skinframe->base)
6671 skinframe->stain = NULL;
6672 skinframe->merged = NULL;
6673 skinframe->base = NULL;
6674 skinframe->pants = NULL;
6675 skinframe->shirt = NULL;
6676 skinframe->nmap = NULL;
6677 skinframe->gloss = NULL;
6678 skinframe->glow = NULL;
6679 skinframe->fog = NULL;
6680 skinframe->reflect = NULL;
6681 skinframe->hasalpha = false;
6683 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6687 if (developer_loading.integer)
6688 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6690 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6691 if (textureflags & TEXF_ALPHA)
6693 for (i = 0;i < width * height;i++)
6695 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6697 skinframe->hasalpha = true;
6701 if (r_loadfog && skinframe->hasalpha)
6702 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6705 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6706 //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]);
6711 skinframe_t *R_SkinFrame_LoadMissing(void)
6713 skinframe_t *skinframe;
6715 if (cls.state == ca_dedicated)
6718 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6719 skinframe->stain = NULL;
6720 skinframe->merged = NULL;
6721 skinframe->base = NULL;
6722 skinframe->pants = NULL;
6723 skinframe->shirt = NULL;
6724 skinframe->nmap = NULL;
6725 skinframe->gloss = NULL;
6726 skinframe->glow = NULL;
6727 skinframe->fog = NULL;
6728 skinframe->reflect = NULL;
6729 skinframe->hasalpha = false;
6731 skinframe->avgcolor[0] = rand() / RAND_MAX;
6732 skinframe->avgcolor[1] = rand() / RAND_MAX;
6733 skinframe->avgcolor[2] = rand() / RAND_MAX;
6734 skinframe->avgcolor[3] = 1;
6739 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6740 typedef struct suffixinfo_s
6743 qboolean flipx, flipy, flipdiagonal;
6746 static suffixinfo_t suffix[3][6] =
6749 {"px", false, false, false},
6750 {"nx", false, false, false},
6751 {"py", false, false, false},
6752 {"ny", false, false, false},
6753 {"pz", false, false, false},
6754 {"nz", false, false, false}
6757 {"posx", false, false, false},
6758 {"negx", false, false, false},
6759 {"posy", false, false, false},
6760 {"negy", false, false, false},
6761 {"posz", false, false, false},
6762 {"negz", false, false, false}
6765 {"rt", true, false, true},
6766 {"lf", false, true, true},
6767 {"ft", true, true, false},
6768 {"bk", false, false, false},
6769 {"up", true, false, true},
6770 {"dn", true, false, true}
6774 static int componentorder[4] = {0, 1, 2, 3};
6776 rtexture_t *R_LoadCubemap(const char *basename)
6778 int i, j, cubemapsize;
6779 unsigned char *cubemappixels, *image_buffer;
6780 rtexture_t *cubemaptexture;
6782 // must start 0 so the first loadimagepixels has no requested width/height
6784 cubemappixels = NULL;
6785 cubemaptexture = NULL;
6786 // keep trying different suffix groups (posx, px, rt) until one loads
6787 for (j = 0;j < 3 && !cubemappixels;j++)
6789 // load the 6 images in the suffix group
6790 for (i = 0;i < 6;i++)
6792 // generate an image name based on the base and and suffix
6793 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6795 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6797 // an image loaded, make sure width and height are equal
6798 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6800 // if this is the first image to load successfully, allocate the cubemap memory
6801 if (!cubemappixels && image_width >= 1)
6803 cubemapsize = image_width;
6804 // note this clears to black, so unavailable sides are black
6805 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6807 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6809 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);
6812 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6814 Mem_Free(image_buffer);
6818 // if a cubemap loaded, upload it
6821 if (developer_loading.integer)
6822 Con_Printf("loading cubemap \"%s\"\n", basename);
6824 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6825 Mem_Free(cubemappixels);
6829 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6830 if (developer_loading.integer)
6832 Con_Printf("(tried tried images ");
6833 for (j = 0;j < 3;j++)
6834 for (i = 0;i < 6;i++)
6835 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6836 Con_Print(" and was unable to find any of them).\n");
6839 return cubemaptexture;
6842 rtexture_t *R_GetCubemap(const char *basename)
6845 for (i = 0;i < r_texture_numcubemaps;i++)
6846 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6847 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6848 if (i >= MAX_CUBEMAPS)
6849 return r_texture_whitecube;
6850 r_texture_numcubemaps++;
6851 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6852 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6853 return r_texture_cubemaps[i].texture;
6856 void R_FreeCubemaps(void)
6859 for (i = 0;i < r_texture_numcubemaps;i++)
6861 if (developer_loading.integer)
6862 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6863 if (r_texture_cubemaps[i].texture)
6864 R_FreeTexture(r_texture_cubemaps[i].texture);
6866 r_texture_numcubemaps = 0;
6869 void R_Main_FreeViewCache(void)
6871 if (r_refdef.viewcache.entityvisible)
6872 Mem_Free(r_refdef.viewcache.entityvisible);
6873 if (r_refdef.viewcache.world_pvsbits)
6874 Mem_Free(r_refdef.viewcache.world_pvsbits);
6875 if (r_refdef.viewcache.world_leafvisible)
6876 Mem_Free(r_refdef.viewcache.world_leafvisible);
6877 if (r_refdef.viewcache.world_surfacevisible)
6878 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6879 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6882 void R_Main_ResizeViewCache(void)
6884 int numentities = r_refdef.scene.numentities;
6885 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6886 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6887 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6888 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6889 if (r_refdef.viewcache.maxentities < numentities)
6891 r_refdef.viewcache.maxentities = numentities;
6892 if (r_refdef.viewcache.entityvisible)
6893 Mem_Free(r_refdef.viewcache.entityvisible);
6894 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6896 if (r_refdef.viewcache.world_numclusters != numclusters)
6898 r_refdef.viewcache.world_numclusters = numclusters;
6899 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6900 if (r_refdef.viewcache.world_pvsbits)
6901 Mem_Free(r_refdef.viewcache.world_pvsbits);
6902 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6904 if (r_refdef.viewcache.world_numleafs != numleafs)
6906 r_refdef.viewcache.world_numleafs = numleafs;
6907 if (r_refdef.viewcache.world_leafvisible)
6908 Mem_Free(r_refdef.viewcache.world_leafvisible);
6909 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6911 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6913 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6914 if (r_refdef.viewcache.world_surfacevisible)
6915 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6916 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6920 extern rtexture_t *loadingscreentexture;
6921 void gl_main_start(void)
6923 loadingscreentexture = NULL;
6924 r_texture_blanknormalmap = NULL;
6925 r_texture_white = NULL;
6926 r_texture_grey128 = NULL;
6927 r_texture_black = NULL;
6928 r_texture_whitecube = NULL;
6929 r_texture_normalizationcube = NULL;
6930 r_texture_fogattenuation = NULL;
6931 r_texture_fogheighttexture = NULL;
6932 r_texture_gammaramps = NULL;
6933 r_texture_numcubemaps = 0;
6935 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6936 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6938 switch(vid.renderpath)
6940 case RENDERPATH_GL20:
6941 case RENDERPATH_CGGL:
6942 case RENDERPATH_D3D9:
6943 case RENDERPATH_D3D10:
6944 case RENDERPATH_D3D11:
6945 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6946 Cvar_SetValueQuick(&gl_combine, 1);
6947 Cvar_SetValueQuick(&r_glsl, 1);
6948 r_loadnormalmap = true;
6952 case RENDERPATH_GL13:
6953 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6954 Cvar_SetValueQuick(&gl_combine, 1);
6955 Cvar_SetValueQuick(&r_glsl, 0);
6956 r_loadnormalmap = false;
6957 r_loadgloss = false;
6960 case RENDERPATH_GL11:
6961 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6962 Cvar_SetValueQuick(&gl_combine, 0);
6963 Cvar_SetValueQuick(&r_glsl, 0);
6964 r_loadnormalmap = false;
6965 r_loadgloss = false;
6971 R_FrameData_Reset();
6975 memset(r_queries, 0, sizeof(r_queries));
6977 r_qwskincache = NULL;
6978 r_qwskincache_size = 0;
6980 // set up r_skinframe loading system for textures
6981 memset(&r_skinframe, 0, sizeof(r_skinframe));
6982 r_skinframe.loadsequence = 1;
6983 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6985 r_main_texturepool = R_AllocTexturePool();
6986 R_BuildBlankTextures();
6988 if (vid.support.arb_texture_cube_map)
6991 R_BuildNormalizationCube();
6993 r_texture_fogattenuation = NULL;
6994 r_texture_fogheighttexture = NULL;
6995 r_texture_gammaramps = NULL;
6996 //r_texture_fogintensity = NULL;
6997 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6998 memset(&r_waterstate, 0, sizeof(r_waterstate));
6999 r_glsl_permutation = NULL;
7000 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7001 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7002 glslshaderstring = NULL;
7004 r_cg_permutation = NULL;
7005 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7006 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7007 cgshaderstring = NULL;
7010 r_hlsl_permutation = NULL;
7011 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7012 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7013 hlslshaderstring = NULL;
7015 memset(&r_svbsp, 0, sizeof (r_svbsp));
7017 r_refdef.fogmasktable_density = 0;
7020 void gl_main_shutdown(void)
7023 R_FrameData_Reset();
7025 R_Main_FreeViewCache();
7027 switch(vid.renderpath)
7029 case RENDERPATH_GL11:
7030 case RENDERPATH_GL13:
7031 case RENDERPATH_GL20:
7032 case RENDERPATH_CGGL:
7034 qglDeleteQueriesARB(r_maxqueries, r_queries);
7036 case RENDERPATH_D3D9:
7037 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7039 case RENDERPATH_D3D10:
7040 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7042 case RENDERPATH_D3D11:
7043 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7049 memset(r_queries, 0, sizeof(r_queries));
7051 r_qwskincache = NULL;
7052 r_qwskincache_size = 0;
7054 // clear out the r_skinframe state
7055 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7056 memset(&r_skinframe, 0, sizeof(r_skinframe));
7059 Mem_Free(r_svbsp.nodes);
7060 memset(&r_svbsp, 0, sizeof (r_svbsp));
7061 R_FreeTexturePool(&r_main_texturepool);
7062 loadingscreentexture = NULL;
7063 r_texture_blanknormalmap = NULL;
7064 r_texture_white = NULL;
7065 r_texture_grey128 = NULL;
7066 r_texture_black = NULL;
7067 r_texture_whitecube = NULL;
7068 r_texture_normalizationcube = NULL;
7069 r_texture_fogattenuation = NULL;
7070 r_texture_fogheighttexture = NULL;
7071 r_texture_gammaramps = NULL;
7072 r_texture_numcubemaps = 0;
7073 //r_texture_fogintensity = NULL;
7074 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7075 memset(&r_waterstate, 0, sizeof(r_waterstate));
7079 extern void CL_ParseEntityLump(char *entitystring);
7080 void gl_main_newmap(void)
7082 // FIXME: move this code to client
7083 char *entities, entname[MAX_QPATH];
7085 Mem_Free(r_qwskincache);
7086 r_qwskincache = NULL;
7087 r_qwskincache_size = 0;
7090 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7091 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7093 CL_ParseEntityLump(entities);
7097 if (cl.worldmodel->brush.entities)
7098 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7100 R_Main_FreeViewCache();
7102 R_FrameData_Reset();
7105 void GL_Main_Init(void)
7107 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7109 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7110 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7111 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7112 if (gamemode == GAME_NEHAHRA)
7114 Cvar_RegisterVariable (&gl_fogenable);
7115 Cvar_RegisterVariable (&gl_fogdensity);
7116 Cvar_RegisterVariable (&gl_fogred);
7117 Cvar_RegisterVariable (&gl_foggreen);
7118 Cvar_RegisterVariable (&gl_fogblue);
7119 Cvar_RegisterVariable (&gl_fogstart);
7120 Cvar_RegisterVariable (&gl_fogend);
7121 Cvar_RegisterVariable (&gl_skyclip);
7123 Cvar_RegisterVariable(&r_motionblur);
7124 Cvar_RegisterVariable(&r_motionblur_maxblur);
7125 Cvar_RegisterVariable(&r_motionblur_bmin);
7126 Cvar_RegisterVariable(&r_motionblur_vmin);
7127 Cvar_RegisterVariable(&r_motionblur_vmax);
7128 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7129 Cvar_RegisterVariable(&r_motionblur_randomize);
7130 Cvar_RegisterVariable(&r_damageblur);
7131 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7132 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7133 Cvar_RegisterVariable(&r_equalize_entities_by);
7134 Cvar_RegisterVariable(&r_equalize_entities_to);
7135 Cvar_RegisterVariable(&r_depthfirst);
7136 Cvar_RegisterVariable(&r_useinfinitefarclip);
7137 Cvar_RegisterVariable(&r_farclip_base);
7138 Cvar_RegisterVariable(&r_farclip_world);
7139 Cvar_RegisterVariable(&r_nearclip);
7140 Cvar_RegisterVariable(&r_showbboxes);
7141 Cvar_RegisterVariable(&r_showsurfaces);
7142 Cvar_RegisterVariable(&r_showtris);
7143 Cvar_RegisterVariable(&r_shownormals);
7144 Cvar_RegisterVariable(&r_showlighting);
7145 Cvar_RegisterVariable(&r_showshadowvolumes);
7146 Cvar_RegisterVariable(&r_showcollisionbrushes);
7147 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7148 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7149 Cvar_RegisterVariable(&r_showdisabledepthtest);
7150 Cvar_RegisterVariable(&r_drawportals);
7151 Cvar_RegisterVariable(&r_drawentities);
7152 Cvar_RegisterVariable(&r_draw2d);
7153 Cvar_RegisterVariable(&r_drawworld);
7154 Cvar_RegisterVariable(&r_cullentities_trace);
7155 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7156 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7157 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7158 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7159 Cvar_RegisterVariable(&r_drawviewmodel);
7160 Cvar_RegisterVariable(&r_drawexteriormodel);
7161 Cvar_RegisterVariable(&r_speeds);
7162 Cvar_RegisterVariable(&r_fullbrights);
7163 Cvar_RegisterVariable(&r_wateralpha);
7164 Cvar_RegisterVariable(&r_dynamic);
7165 Cvar_RegisterVariable(&r_fullbright);
7166 Cvar_RegisterVariable(&r_shadows);
7167 Cvar_RegisterVariable(&r_shadows_darken);
7168 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7169 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7170 Cvar_RegisterVariable(&r_shadows_throwdistance);
7171 Cvar_RegisterVariable(&r_shadows_throwdirection);
7172 Cvar_RegisterVariable(&r_shadows_focus);
7173 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7174 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7175 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7176 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7177 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7178 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7179 Cvar_RegisterVariable(&r_fog_exp2);
7180 Cvar_RegisterVariable(&r_drawfog);
7181 Cvar_RegisterVariable(&r_transparentdepthmasking);
7182 Cvar_RegisterVariable(&r_texture_dds_load);
7183 Cvar_RegisterVariable(&r_texture_dds_save);
7184 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7185 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7186 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7187 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7188 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7189 Cvar_RegisterVariable(&r_textureunits);
7190 Cvar_RegisterVariable(&gl_combine);
7191 Cvar_RegisterVariable(&r_glsl);
7192 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7193 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7194 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7195 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7196 Cvar_RegisterVariable(&r_glsl_postprocess);
7197 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7198 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7199 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7200 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7201 Cvar_RegisterVariable(&r_water);
7202 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7203 Cvar_RegisterVariable(&r_water_clippingplanebias);
7204 Cvar_RegisterVariable(&r_water_refractdistort);
7205 Cvar_RegisterVariable(&r_water_reflectdistort);
7206 Cvar_RegisterVariable(&r_lerpsprites);
7207 Cvar_RegisterVariable(&r_lerpmodels);
7208 Cvar_RegisterVariable(&r_lerplightstyles);
7209 Cvar_RegisterVariable(&r_waterscroll);
7210 Cvar_RegisterVariable(&r_bloom);
7211 Cvar_RegisterVariable(&r_bloom_colorscale);
7212 Cvar_RegisterVariable(&r_bloom_brighten);
7213 Cvar_RegisterVariable(&r_bloom_blur);
7214 Cvar_RegisterVariable(&r_bloom_resolution);
7215 Cvar_RegisterVariable(&r_bloom_colorexponent);
7216 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7217 Cvar_RegisterVariable(&r_hdr);
7218 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7219 Cvar_RegisterVariable(&r_hdr_glowintensity);
7220 Cvar_RegisterVariable(&r_hdr_range);
7221 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7222 Cvar_RegisterVariable(&developer_texturelogging);
7223 Cvar_RegisterVariable(&gl_lightmaps);
7224 Cvar_RegisterVariable(&r_test);
7225 Cvar_RegisterVariable(&r_glsl_saturation);
7226 Cvar_RegisterVariable(&r_framedatasize);
7227 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7228 Cvar_SetValue("r_fullbrights", 0);
7229 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7231 Cvar_RegisterVariable(&r_track_sprites);
7232 Cvar_RegisterVariable(&r_track_sprites_flags);
7233 Cvar_RegisterVariable(&r_track_sprites_scalew);
7234 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7235 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7236 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7239 extern void R_Textures_Init(void);
7240 extern void GL_Draw_Init(void);
7241 extern void GL_Main_Init(void);
7242 extern void R_Shadow_Init(void);
7243 extern void R_Sky_Init(void);
7244 extern void GL_Surf_Init(void);
7245 extern void R_Particles_Init(void);
7246 extern void R_Explosion_Init(void);
7247 extern void gl_backend_init(void);
7248 extern void Sbar_Init(void);
7249 extern void R_LightningBeams_Init(void);
7250 extern void Mod_RenderInit(void);
7251 extern void Font_Init(void);
7253 void Render_Init(void)
7266 R_LightningBeams_Init();
7275 extern char *ENGINE_EXTENSIONS;
7278 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7279 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7280 gl_version = (const char *)qglGetString(GL_VERSION);
7281 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7285 if (!gl_platformextensions)
7286 gl_platformextensions = "";
7288 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7289 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7290 Con_Printf("GL_VERSION: %s\n", gl_version);
7291 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7292 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7294 VID_CheckExtensions();
7296 // LordHavoc: report supported extensions
7297 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7299 // clear to black (loading plaque will be seen over this)
7300 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7303 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7307 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7309 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7312 p = r_refdef.view.frustum + i;
7317 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7321 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7325 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7329 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7333 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7337 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7341 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7345 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7353 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7357 for (i = 0;i < numplanes;i++)
7364 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7368 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7372 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7376 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7380 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7384 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7388 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7392 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7400 //==================================================================================
7402 // LordHavoc: this stores temporary data used within the same frame
7404 qboolean r_framedata_failed;
7405 static size_t r_framedata_size;
7406 static size_t r_framedata_current;
7407 static void *r_framedata_base;
7409 void R_FrameData_Reset(void)
7411 if (r_framedata_base)
7412 Mem_Free(r_framedata_base);
7413 r_framedata_base = NULL;
7414 r_framedata_size = 0;
7415 r_framedata_current = 0;
7416 r_framedata_failed = false;
7419 void R_FrameData_NewFrame(void)
7422 if (r_framedata_failed)
7423 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7424 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7425 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7426 if (r_framedata_size != wantedsize)
7428 r_framedata_size = wantedsize;
7429 if (r_framedata_base)
7430 Mem_Free(r_framedata_base);
7431 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7433 r_framedata_current = 0;
7434 r_framedata_failed = false;
7437 void *R_FrameData_Alloc(size_t size)
7441 // align to 16 byte boundary
7442 size = (size + 15) & ~15;
7443 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7444 r_framedata_current += size;
7447 if (r_framedata_current > r_framedata_size)
7448 r_framedata_failed = true;
7450 // return NULL on everything after a failure
7451 if (r_framedata_failed)
7457 void *R_FrameData_Store(size_t size, void *data)
7459 void *d = R_FrameData_Alloc(size);
7461 memcpy(d, data, size);
7465 //==================================================================================
7467 // LordHavoc: animcache originally written by Echon, rewritten since then
7470 * Animation cache prevents re-generating mesh data for an animated model
7471 * multiple times in one frame for lighting, shadowing, reflections, etc.
7474 void R_AnimCache_Free(void)
7478 void R_AnimCache_ClearCache(void)
7481 entity_render_t *ent;
7483 for (i = 0;i < r_refdef.scene.numentities;i++)
7485 ent = r_refdef.scene.entities[i];
7486 ent->animcache_vertex3f = NULL;
7487 ent->animcache_normal3f = NULL;
7488 ent->animcache_svector3f = NULL;
7489 ent->animcache_tvector3f = NULL;
7490 ent->animcache_vertexposition = NULL;
7491 ent->animcache_vertexmesh = NULL;
7492 ent->animcache_vertexpositionbuffer = NULL;
7493 ent->animcache_vertexmeshbuffer = NULL;
7497 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7501 // identical memory layout, so no need to allocate...
7502 // this also provides the vertexposition structure to everything, e.g.
7503 // depth masked rendering currently uses it even if having separate
7505 // NOTE: get rid of this optimization if changing it to e.g. 4f
7506 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7509 // get rid of following uses of VERTEXPOSITION, change to the array:
7510 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7511 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7512 // R_DrawTextureSurfaceList_DepthOnly
7513 // R_Q1BSP_DrawShadowMap
7515 switch(vid.renderpath)
7517 case RENDERPATH_GL20:
7518 case RENDERPATH_CGGL:
7519 // need the meshbuffers if !gl_mesh_separatearrays.integer
7520 if (gl_mesh_separatearrays.integer)
7523 case RENDERPATH_D3D9:
7524 case RENDERPATH_D3D10:
7525 case RENDERPATH_D3D11:
7526 // always need the meshbuffers
7528 case RENDERPATH_GL13:
7529 case RENDERPATH_GL11:
7530 // never need the meshbuffers
7534 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7535 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7537 if (!ent->animcache_vertexposition)
7538 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7540 if (ent->animcache_vertexposition)
7543 for (i = 0;i < numvertices;i++)
7544 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7546 // TODO: upload vertex buffer?
7548 if (ent->animcache_vertexmesh)
7550 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7551 for (i = 0;i < numvertices;i++)
7552 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7553 if (ent->animcache_svector3f)
7554 for (i = 0;i < numvertices;i++)
7555 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7556 if (ent->animcache_tvector3f)
7557 for (i = 0;i < numvertices;i++)
7558 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7559 if (ent->animcache_normal3f)
7560 for (i = 0;i < numvertices;i++)
7561 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7562 // TODO: upload vertex buffer?
7566 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7568 dp_model_t *model = ent->model;
7570 // see if it's already cached this frame
7571 if (ent->animcache_vertex3f)
7573 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7574 if (wantnormals || wanttangents)
7576 if (ent->animcache_normal3f)
7577 wantnormals = false;
7578 if (ent->animcache_svector3f)
7579 wanttangents = false;
7580 if (wantnormals || wanttangents)
7582 numvertices = model->surfmesh.num_vertices;
7584 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7587 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7588 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7590 if (!r_framedata_failed)
7592 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7593 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7600 // see if this ent is worth caching
7601 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7603 // get some memory for this entity and generate mesh data
7604 numvertices = model->surfmesh.num_vertices;
7605 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7607 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7610 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7611 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7613 if (!r_framedata_failed)
7615 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7616 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7619 return !r_framedata_failed;
7622 void R_AnimCache_CacheVisibleEntities(void)
7625 qboolean wantnormals = true;
7626 qboolean wanttangents = !r_showsurfaces.integer;
7628 switch(vid.renderpath)
7630 case RENDERPATH_GL20:
7631 case RENDERPATH_CGGL:
7632 case RENDERPATH_D3D9:
7633 case RENDERPATH_D3D10:
7634 case RENDERPATH_D3D11:
7636 case RENDERPATH_GL13:
7637 case RENDERPATH_GL11:
7638 wanttangents = false;
7642 if (r_shownormals.integer)
7643 wanttangents = wantnormals = true;
7645 // TODO: thread this
7646 // NOTE: R_PrepareRTLights() also caches entities
7648 for (i = 0;i < r_refdef.scene.numentities;i++)
7649 if (r_refdef.viewcache.entityvisible[i])
7650 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7653 //==================================================================================
7655 static void R_View_UpdateEntityLighting (void)
7658 entity_render_t *ent;
7659 vec3_t tempdiffusenormal, avg;
7660 vec_t f, fa, fd, fdd;
7661 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7663 for (i = 0;i < r_refdef.scene.numentities;i++)
7665 ent = r_refdef.scene.entities[i];
7667 // skip unseen models
7668 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7672 if (ent->model && ent->model->brush.num_leafs)
7674 // TODO: use modellight for r_ambient settings on world?
7675 VectorSet(ent->modellight_ambient, 0, 0, 0);
7676 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7677 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7681 // fetch the lighting from the worldmodel data
7682 VectorClear(ent->modellight_ambient);
7683 VectorClear(ent->modellight_diffuse);
7684 VectorClear(tempdiffusenormal);
7685 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7688 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7689 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7690 if(ent->flags & RENDER_EQUALIZE)
7692 // first fix up ambient lighting...
7693 if(r_equalize_entities_minambient.value > 0)
7695 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7698 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7699 if(fa < r_equalize_entities_minambient.value * fd)
7702 // fa'/fd' = minambient
7703 // fa'+0.25*fd' = fa+0.25*fd
7705 // fa' = fd' * minambient
7706 // fd'*(0.25+minambient) = fa+0.25*fd
7708 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7709 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7711 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7712 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
7713 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7714 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7719 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7721 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7722 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7725 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7726 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7727 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7733 VectorSet(ent->modellight_ambient, 1, 1, 1);
7735 // move the light direction into modelspace coordinates for lighting code
7736 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7737 if(VectorLength2(ent->modellight_lightdir) == 0)
7738 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7739 VectorNormalize(ent->modellight_lightdir);
7743 #define MAX_LINEOFSIGHTTRACES 64
7745 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7748 vec3_t boxmins, boxmaxs;
7751 dp_model_t *model = r_refdef.scene.worldmodel;
7753 if (!model || !model->brush.TraceLineOfSight)
7756 // expand the box a little
7757 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7758 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7759 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7760 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7761 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7762 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7764 // return true if eye is inside enlarged box
7765 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7769 VectorCopy(eye, start);
7770 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7771 if (model->brush.TraceLineOfSight(model, start, end))
7774 // try various random positions
7775 for (i = 0;i < numsamples;i++)
7777 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7778 if (model->brush.TraceLineOfSight(model, start, end))
7786 static void R_View_UpdateEntityVisible (void)
7791 entity_render_t *ent;
7793 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7794 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7795 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7796 : RENDER_EXTERIORMODEL;
7797 if (!r_drawviewmodel.integer)
7798 renderimask |= RENDER_VIEWMODEL;
7799 if (!r_drawexteriormodel.integer)
7800 renderimask |= RENDER_EXTERIORMODEL;
7801 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7803 // worldmodel can check visibility
7804 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7805 for (i = 0;i < r_refdef.scene.numentities;i++)
7807 ent = r_refdef.scene.entities[i];
7808 if (!(ent->flags & renderimask))
7809 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)))
7810 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))
7811 r_refdef.viewcache.entityvisible[i] = true;
7813 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7814 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7816 for (i = 0;i < r_refdef.scene.numentities;i++)
7818 ent = r_refdef.scene.entities[i];
7819 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7821 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7823 continue; // temp entities do pvs only
7824 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7825 ent->last_trace_visibility = realtime;
7826 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7827 r_refdef.viewcache.entityvisible[i] = 0;
7834 // no worldmodel or it can't check visibility
7835 for (i = 0;i < r_refdef.scene.numentities;i++)
7837 ent = r_refdef.scene.entities[i];
7838 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));
7843 /// only used if skyrendermasked, and normally returns false
7844 int R_DrawBrushModelsSky (void)
7847 entity_render_t *ent;
7850 for (i = 0;i < r_refdef.scene.numentities;i++)
7852 if (!r_refdef.viewcache.entityvisible[i])
7854 ent = r_refdef.scene.entities[i];
7855 if (!ent->model || !ent->model->DrawSky)
7857 ent->model->DrawSky(ent);
7863 static void R_DrawNoModel(entity_render_t *ent);
7864 static void R_DrawModels(void)
7867 entity_render_t *ent;
7869 for (i = 0;i < r_refdef.scene.numentities;i++)
7871 if (!r_refdef.viewcache.entityvisible[i])
7873 ent = r_refdef.scene.entities[i];
7874 r_refdef.stats.entities++;
7875 if (ent->model && ent->model->Draw != NULL)
7876 ent->model->Draw(ent);
7882 static void R_DrawModelsDepth(void)
7885 entity_render_t *ent;
7887 for (i = 0;i < r_refdef.scene.numentities;i++)
7889 if (!r_refdef.viewcache.entityvisible[i])
7891 ent = r_refdef.scene.entities[i];
7892 if (ent->model && ent->model->DrawDepth != NULL)
7893 ent->model->DrawDepth(ent);
7897 static void R_DrawModelsDebug(void)
7900 entity_render_t *ent;
7902 for (i = 0;i < r_refdef.scene.numentities;i++)
7904 if (!r_refdef.viewcache.entityvisible[i])
7906 ent = r_refdef.scene.entities[i];
7907 if (ent->model && ent->model->DrawDebug != NULL)
7908 ent->model->DrawDebug(ent);
7912 static void R_DrawModelsAddWaterPlanes(void)
7915 entity_render_t *ent;
7917 for (i = 0;i < r_refdef.scene.numentities;i++)
7919 if (!r_refdef.viewcache.entityvisible[i])
7921 ent = r_refdef.scene.entities[i];
7922 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7923 ent->model->DrawAddWaterPlanes(ent);
7927 static void R_View_SetFrustum(void)
7930 double slopex, slopey;
7931 vec3_t forward, left, up, origin;
7933 // we can't trust r_refdef.view.forward and friends in reflected scenes
7934 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7937 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7938 r_refdef.view.frustum[0].normal[1] = 0 - 0;
7939 r_refdef.view.frustum[0].normal[2] = -1 - 0;
7940 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7941 r_refdef.view.frustum[1].normal[1] = 0 + 0;
7942 r_refdef.view.frustum[1].normal[2] = -1 + 0;
7943 r_refdef.view.frustum[2].normal[0] = 0 - 0;
7944 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7945 r_refdef.view.frustum[2].normal[2] = -1 - 0;
7946 r_refdef.view.frustum[3].normal[0] = 0 + 0;
7947 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7948 r_refdef.view.frustum[3].normal[2] = -1 + 0;
7952 zNear = r_refdef.nearclip;
7953 nudge = 1.0 - 1.0 / (1<<23);
7954 r_refdef.view.frustum[4].normal[0] = 0 - 0;
7955 r_refdef.view.frustum[4].normal[1] = 0 - 0;
7956 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7957 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7958 r_refdef.view.frustum[5].normal[0] = 0 + 0;
7959 r_refdef.view.frustum[5].normal[1] = 0 + 0;
7960 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7961 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7967 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7968 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7969 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7970 r_refdef.view.frustum[0].dist = m[15] - m[12];
7972 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7973 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7974 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7975 r_refdef.view.frustum[1].dist = m[15] + m[12];
7977 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7978 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7979 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7980 r_refdef.view.frustum[2].dist = m[15] - m[13];
7982 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7983 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7984 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7985 r_refdef.view.frustum[3].dist = m[15] + m[13];
7987 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7988 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7989 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7990 r_refdef.view.frustum[4].dist = m[15] - m[14];
7992 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7993 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7994 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7995 r_refdef.view.frustum[5].dist = m[15] + m[14];
7998 if (r_refdef.view.useperspective)
8000 slopex = 1.0 / r_refdef.view.frustum_x;
8001 slopey = 1.0 / r_refdef.view.frustum_y;
8002 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8003 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
8004 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
8005 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
8006 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8008 // Leaving those out was a mistake, those were in the old code, and they
8009 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8010 // I couldn't reproduce it after adding those normalizations. --blub
8011 VectorNormalize(r_refdef.view.frustum[0].normal);
8012 VectorNormalize(r_refdef.view.frustum[1].normal);
8013 VectorNormalize(r_refdef.view.frustum[2].normal);
8014 VectorNormalize(r_refdef.view.frustum[3].normal);
8016 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8017 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8018 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]);
8019 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]);
8020 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]);
8022 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8023 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8024 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8025 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8026 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8030 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8031 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8032 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8033 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8034 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8035 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8036 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8037 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8038 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8039 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8041 r_refdef.view.numfrustumplanes = 5;
8043 if (r_refdef.view.useclipplane)
8045 r_refdef.view.numfrustumplanes = 6;
8046 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8049 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8050 PlaneClassify(r_refdef.view.frustum + i);
8052 // LordHavoc: note to all quake engine coders, Quake had a special case
8053 // for 90 degrees which assumed a square view (wrong), so I removed it,
8054 // Quake2 has it disabled as well.
8056 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8057 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8058 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8059 //PlaneClassify(&frustum[0]);
8061 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8062 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8063 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8064 //PlaneClassify(&frustum[1]);
8066 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8067 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8068 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8069 //PlaneClassify(&frustum[2]);
8071 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8072 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8073 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8074 //PlaneClassify(&frustum[3]);
8077 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8078 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8079 //PlaneClassify(&frustum[4]);
8082 void R_View_Update(void)
8084 R_Main_ResizeViewCache();
8085 R_View_SetFrustum();
8086 R_View_WorldVisibility(r_refdef.view.useclipplane);
8087 R_View_UpdateEntityVisible();
8088 R_View_UpdateEntityLighting();
8091 void R_SetupView(qboolean allowwaterclippingplane)
8093 const float *customclipplane = NULL;
8095 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8097 // LordHavoc: couldn't figure out how to make this approach the
8098 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8099 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8100 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8101 dist = r_refdef.view.clipplane.dist;
8102 plane[0] = r_refdef.view.clipplane.normal[0];
8103 plane[1] = r_refdef.view.clipplane.normal[1];
8104 plane[2] = r_refdef.view.clipplane.normal[2];
8106 customclipplane = plane;
8109 if (!r_refdef.view.useperspective)
8110 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);
8111 else if (vid.stencil && r_useinfinitefarclip.integer)
8112 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);
8114 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);
8115 R_SetViewport(&r_refdef.view.viewport);
8118 void R_EntityMatrix(const matrix4x4_t *matrix)
8120 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8122 gl_modelmatrixchanged = false;
8123 gl_modelmatrix = *matrix;
8124 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8125 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8126 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8127 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8129 switch(vid.renderpath)
8131 case RENDERPATH_D3D9:
8133 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8134 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8137 case RENDERPATH_D3D10:
8138 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8140 case RENDERPATH_D3D11:
8141 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8143 case RENDERPATH_GL20:
8144 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8145 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8146 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8148 case RENDERPATH_CGGL:
8151 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8152 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8153 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8156 case RENDERPATH_GL13:
8157 case RENDERPATH_GL11:
8158 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8164 void R_ResetViewRendering2D(void)
8166 r_viewport_t viewport;
8169 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8170 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);
8171 R_SetViewport(&viewport);
8172 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8173 GL_Color(1, 1, 1, 1);
8174 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8175 GL_BlendFunc(GL_ONE, GL_ZERO);
8176 GL_AlphaTest(false);
8177 GL_ScissorTest(false);
8178 GL_DepthMask(false);
8179 GL_DepthRange(0, 1);
8180 GL_DepthTest(false);
8181 GL_DepthFunc(GL_LEQUAL);
8182 R_EntityMatrix(&identitymatrix);
8183 R_Mesh_ResetTextureState();
8184 GL_PolygonOffset(0, 0);
8185 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8186 switch(vid.renderpath)
8188 case RENDERPATH_GL11:
8189 case RENDERPATH_GL13:
8190 case RENDERPATH_GL20:
8191 case RENDERPATH_CGGL:
8192 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8194 case RENDERPATH_D3D9:
8195 case RENDERPATH_D3D10:
8196 case RENDERPATH_D3D11:
8199 GL_CullFace(GL_NONE);
8202 void R_ResetViewRendering3D(void)
8207 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8208 GL_Color(1, 1, 1, 1);
8209 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8210 GL_BlendFunc(GL_ONE, GL_ZERO);
8211 GL_AlphaTest(false);
8212 GL_ScissorTest(true);
8214 GL_DepthRange(0, 1);
8216 GL_DepthFunc(GL_LEQUAL);
8217 R_EntityMatrix(&identitymatrix);
8218 R_Mesh_ResetTextureState();
8219 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8220 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8221 switch(vid.renderpath)
8223 case RENDERPATH_GL11:
8224 case RENDERPATH_GL13:
8225 case RENDERPATH_GL20:
8226 case RENDERPATH_CGGL:
8227 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8229 case RENDERPATH_D3D9:
8230 case RENDERPATH_D3D10:
8231 case RENDERPATH_D3D11:
8234 GL_CullFace(r_refdef.view.cullface_back);
8239 R_RenderView_UpdateViewVectors
8242 static void R_RenderView_UpdateViewVectors(void)
8244 // break apart the view matrix into vectors for various purposes
8245 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8246 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8247 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8248 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8249 // make an inverted copy of the view matrix for tracking sprites
8250 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8253 void R_RenderScene(void);
8254 void R_RenderWaterPlanes(void);
8256 static void R_Water_StartFrame(void)
8259 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8260 r_waterstate_waterplane_t *p;
8262 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8265 switch(vid.renderpath)
8267 case RENDERPATH_GL20:
8268 case RENDERPATH_CGGL:
8269 case RENDERPATH_D3D9:
8270 case RENDERPATH_D3D10:
8271 case RENDERPATH_D3D11:
8273 case RENDERPATH_GL13:
8274 case RENDERPATH_GL11:
8278 // set waterwidth and waterheight to the water resolution that will be
8279 // used (often less than the screen resolution for faster rendering)
8280 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8281 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8283 // calculate desired texture sizes
8284 // can't use water if the card does not support the texture size
8285 if (!r_water.integer || r_showsurfaces.integer)
8286 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8287 else if (vid.support.arb_texture_non_power_of_two)
8289 texturewidth = waterwidth;
8290 textureheight = waterheight;
8291 camerawidth = waterwidth;
8292 cameraheight = waterheight;
8296 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8297 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8298 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8299 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8302 // allocate textures as needed
8303 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8305 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8306 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8308 if (p->texture_refraction)
8309 R_FreeTexture(p->texture_refraction);
8310 p->texture_refraction = NULL;
8311 if (p->texture_reflection)
8312 R_FreeTexture(p->texture_reflection);
8313 p->texture_reflection = NULL;
8314 if (p->texture_camera)
8315 R_FreeTexture(p->texture_camera);
8316 p->texture_camera = NULL;
8318 memset(&r_waterstate, 0, sizeof(r_waterstate));
8319 r_waterstate.texturewidth = texturewidth;
8320 r_waterstate.textureheight = textureheight;
8321 r_waterstate.camerawidth = camerawidth;
8322 r_waterstate.cameraheight = cameraheight;
8325 if (r_waterstate.texturewidth)
8327 r_waterstate.enabled = true;
8329 // when doing a reduced render (HDR) we want to use a smaller area
8330 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8331 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8333 // set up variables that will be used in shader setup
8334 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8335 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8336 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8337 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8340 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8341 r_waterstate.numwaterplanes = 0;
8344 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8346 int triangleindex, planeindex;
8353 r_waterstate_waterplane_t *p;
8354 texture_t *t = R_GetCurrentTexture(surface->texture);
8355 cam_ent = t->camera_entity;
8356 if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8359 // just use the first triangle with a valid normal for any decisions
8360 VectorClear(normal);
8361 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8363 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8364 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8365 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8366 TriangleNormal(vert[0], vert[1], vert[2], normal);
8367 if (VectorLength2(normal) >= 0.001)
8371 VectorCopy(normal, plane.normal);
8372 VectorNormalize(plane.normal);
8373 plane.dist = DotProduct(vert[0], plane.normal);
8374 PlaneClassify(&plane);
8375 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8377 // skip backfaces (except if nocullface is set)
8378 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8380 VectorNegate(plane.normal, plane.normal);
8382 PlaneClassify(&plane);
8386 // find a matching plane if there is one
8387 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8388 if(p->camera_entity == t->camera_entity)
8389 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8391 if (planeindex >= r_waterstate.maxwaterplanes)
8392 return; // nothing we can do, out of planes
8394 // if this triangle does not fit any known plane rendered this frame, add one
8395 if (planeindex >= r_waterstate.numwaterplanes)
8397 // store the new plane
8398 r_waterstate.numwaterplanes++;
8400 // clear materialflags and pvs
8401 p->materialflags = 0;
8402 p->pvsvalid = false;
8403 p->camera_entity = t->camera_entity;
8405 // merge this surface's materialflags into the waterplane
8406 p->materialflags |= t->currentmaterialflags;
8407 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8409 // merge this surface's PVS into the waterplane
8410 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8411 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8412 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8414 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8420 static void R_Water_ProcessPlanes(void)
8422 r_refdef_view_t originalview;
8423 r_refdef_view_t myview;
8425 r_waterstate_waterplane_t *p;
8428 originalview = r_refdef.view;
8430 // make sure enough textures are allocated
8431 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8433 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8435 if (!p->texture_refraction)
8436 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);
8437 if (!p->texture_refraction)
8440 else if (p->materialflags & MATERIALFLAG_CAMERA)
8442 if (!p->texture_camera)
8443 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);
8444 if (!p->texture_camera)
8448 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8450 if (!p->texture_reflection)
8451 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);
8452 if (!p->texture_reflection)
8458 r_refdef.view = originalview;
8459 r_refdef.view.showdebug = false;
8460 r_refdef.view.width = r_waterstate.waterwidth;
8461 r_refdef.view.height = r_waterstate.waterheight;
8462 r_refdef.view.useclipplane = true;
8463 myview = r_refdef.view;
8464 r_waterstate.renderingscene = true;
8465 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8467 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8469 r_refdef.view = myview;
8470 // render reflected scene and copy into texture
8471 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8472 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8473 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8474 r_refdef.view.clipplane = p->plane;
8475 // reverse the cullface settings for this render
8476 r_refdef.view.cullface_front = GL_FRONT;
8477 r_refdef.view.cullface_back = GL_BACK;
8478 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8480 r_refdef.view.usecustompvs = true;
8482 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8484 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8487 R_ResetViewRendering3D();
8488 R_ClearScreen(r_refdef.fogenabled);
8492 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);
8495 // render the normal view scene and copy into texture
8496 // (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)
8497 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8499 r_waterstate.renderingrefraction = true;
8500 r_refdef.view = myview;
8502 r_refdef.view.clipplane = p->plane;
8503 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8504 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8506 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8508 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8509 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8510 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8511 R_RenderView_UpdateViewVectors();
8512 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8514 r_refdef.view.usecustompvs = true;
8515 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);
8519 PlaneClassify(&r_refdef.view.clipplane);
8521 R_ResetViewRendering3D();
8522 R_ClearScreen(r_refdef.fogenabled);
8526 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);
8527 r_waterstate.renderingrefraction = false;
8529 else if (p->materialflags & MATERIALFLAG_CAMERA)
8531 r_refdef.view = myview;
8533 r_refdef.view.clipplane = p->plane;
8534 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8535 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8537 r_refdef.view.width = r_waterstate.camerawidth;
8538 r_refdef.view.height = r_waterstate.cameraheight;
8539 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8540 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8542 if(p->camera_entity)
8544 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8545 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8548 // reverse the cullface settings for this render
8549 r_refdef.view.cullface_front = GL_FRONT;
8550 r_refdef.view.cullface_back = GL_BACK;
8551 // also reverse the view matrix
8552 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
8553 R_RenderView_UpdateViewVectors();
8554 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8556 r_refdef.view.usecustompvs = true;
8557 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);
8560 // camera needs no clipplane
8561 r_refdef.view.useclipplane = false;
8563 PlaneClassify(&r_refdef.view.clipplane);
8565 R_ResetViewRendering3D();
8566 R_ClearScreen(r_refdef.fogenabled);
8570 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);
8571 r_waterstate.renderingrefraction = false;
8575 r_waterstate.renderingscene = false;
8576 r_refdef.view = originalview;
8577 R_ResetViewRendering3D();
8578 R_ClearScreen(r_refdef.fogenabled);
8582 r_refdef.view = originalview;
8583 r_waterstate.renderingscene = false;
8584 Cvar_SetValueQuick(&r_water, 0);
8585 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8589 void R_Bloom_StartFrame(void)
8591 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8593 switch(vid.renderpath)
8595 case RENDERPATH_GL20:
8596 case RENDERPATH_CGGL:
8597 case RENDERPATH_D3D9:
8598 case RENDERPATH_D3D10:
8599 case RENDERPATH_D3D11:
8601 case RENDERPATH_GL13:
8602 case RENDERPATH_GL11:
8606 // set bloomwidth and bloomheight to the bloom resolution that will be
8607 // used (often less than the screen resolution for faster rendering)
8608 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8609 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8610 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8611 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8612 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8614 // calculate desired texture sizes
8615 if (vid.support.arb_texture_non_power_of_two)
8617 screentexturewidth = r_refdef.view.width;
8618 screentextureheight = r_refdef.view.height;
8619 bloomtexturewidth = r_bloomstate.bloomwidth;
8620 bloomtextureheight = r_bloomstate.bloomheight;
8624 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8625 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8626 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8627 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8630 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))
8632 Cvar_SetValueQuick(&r_hdr, 0);
8633 Cvar_SetValueQuick(&r_bloom, 0);
8634 Cvar_SetValueQuick(&r_motionblur, 0);
8635 Cvar_SetValueQuick(&r_damageblur, 0);
8638 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)))
8639 screentexturewidth = screentextureheight = 0;
8640 if (!r_hdr.integer && !r_bloom.integer)
8641 bloomtexturewidth = bloomtextureheight = 0;
8643 // allocate textures as needed
8644 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8646 if (r_bloomstate.texture_screen)
8647 R_FreeTexture(r_bloomstate.texture_screen);
8648 r_bloomstate.texture_screen = NULL;
8649 r_bloomstate.screentexturewidth = screentexturewidth;
8650 r_bloomstate.screentextureheight = screentextureheight;
8651 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8652 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);
8654 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8656 if (r_bloomstate.texture_bloom)
8657 R_FreeTexture(r_bloomstate.texture_bloom);
8658 r_bloomstate.texture_bloom = NULL;
8659 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8660 r_bloomstate.bloomtextureheight = bloomtextureheight;
8661 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8662 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);
8665 // when doing a reduced render (HDR) we want to use a smaller area
8666 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8667 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8668 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8669 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8670 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8672 // set up a texcoord array for the full resolution screen image
8673 // (we have to keep this around to copy back during final render)
8674 r_bloomstate.screentexcoord2f[0] = 0;
8675 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8676 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8677 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8678 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8679 r_bloomstate.screentexcoord2f[5] = 0;
8680 r_bloomstate.screentexcoord2f[6] = 0;
8681 r_bloomstate.screentexcoord2f[7] = 0;
8683 // set up a texcoord array for the reduced resolution bloom image
8684 // (which will be additive blended over the screen image)
8685 r_bloomstate.bloomtexcoord2f[0] = 0;
8686 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8687 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8688 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8689 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8690 r_bloomstate.bloomtexcoord2f[5] = 0;
8691 r_bloomstate.bloomtexcoord2f[6] = 0;
8692 r_bloomstate.bloomtexcoord2f[7] = 0;
8694 switch(vid.renderpath)
8696 case RENDERPATH_GL11:
8697 case RENDERPATH_GL13:
8698 case RENDERPATH_GL20:
8699 case RENDERPATH_CGGL:
8701 case RENDERPATH_D3D9:
8702 case RENDERPATH_D3D10:
8703 case RENDERPATH_D3D11:
8706 for (i = 0;i < 4;i++)
8708 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8709 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8710 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8711 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8717 if (r_hdr.integer || r_bloom.integer)
8719 r_bloomstate.enabled = true;
8720 r_bloomstate.hdr = r_hdr.integer != 0;
8723 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);
8726 void R_Bloom_CopyBloomTexture(float colorscale)
8728 r_refdef.stats.bloom++;
8730 // scale down screen texture to the bloom texture size
8732 R_SetViewport(&r_bloomstate.viewport);
8733 GL_BlendFunc(GL_ONE, GL_ZERO);
8734 GL_Color(colorscale, colorscale, colorscale, 1);
8735 // 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...
8736 switch(vid.renderpath)
8738 case RENDERPATH_GL11:
8739 case RENDERPATH_GL13:
8740 case RENDERPATH_GL20:
8741 case RENDERPATH_CGGL:
8742 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8744 case RENDERPATH_D3D9:
8745 case RENDERPATH_D3D10:
8746 case RENDERPATH_D3D11:
8747 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8750 // TODO: do boxfilter scale-down in shader?
8751 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8752 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8753 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8755 // we now have a bloom image in the framebuffer
8756 // copy it into the bloom image texture for later processing
8757 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);
8758 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8761 void R_Bloom_CopyHDRTexture(void)
8763 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);
8764 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8767 void R_Bloom_MakeTexture(void)
8770 float xoffset, yoffset, r, brighten;
8772 r_refdef.stats.bloom++;
8774 R_ResetViewRendering2D();
8776 // we have a bloom image in the framebuffer
8778 R_SetViewport(&r_bloomstate.viewport);
8780 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8783 r = bound(0, r_bloom_colorexponent.value / x, 1);
8784 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8786 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8787 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8788 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8789 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8791 // copy the vertically blurred bloom view to a texture
8792 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);
8793 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8796 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8797 brighten = r_bloom_brighten.value;
8799 brighten *= r_hdr_range.value;
8800 brighten = sqrt(brighten);
8802 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8803 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8805 for (dir = 0;dir < 2;dir++)
8807 // blend on at multiple vertical offsets to achieve a vertical blur
8808 // TODO: do offset blends using GLSL
8809 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8810 GL_BlendFunc(GL_ONE, GL_ZERO);
8811 for (x = -range;x <= range;x++)
8813 if (!dir){xoffset = 0;yoffset = x;}
8814 else {xoffset = x;yoffset = 0;}
8815 xoffset /= (float)r_bloomstate.bloomtexturewidth;
8816 yoffset /= (float)r_bloomstate.bloomtextureheight;
8817 // compute a texcoord array with the specified x and y offset
8818 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8819 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8820 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8821 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8822 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8823 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8824 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8825 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8826 // this r value looks like a 'dot' particle, fading sharply to
8827 // black at the edges
8828 // (probably not realistic but looks good enough)
8829 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8830 //r = brighten/(range*2+1);
8831 r = brighten / (range * 2 + 1);
8833 r *= (1 - x*x/(float)(range*range));
8834 GL_Color(r, r, r, 1);
8835 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8836 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8837 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8838 GL_BlendFunc(GL_ONE, GL_ONE);
8841 // copy the vertically blurred bloom view to a texture
8842 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);
8843 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8847 void R_HDR_RenderBloomTexture(void)
8849 int oldwidth, oldheight;
8850 float oldcolorscale;
8852 oldcolorscale = r_refdef.view.colorscale;
8853 oldwidth = r_refdef.view.width;
8854 oldheight = r_refdef.view.height;
8855 r_refdef.view.width = r_bloomstate.bloomwidth;
8856 r_refdef.view.height = r_bloomstate.bloomheight;
8858 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
8859 // TODO: add exposure compensation features
8860 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8862 r_refdef.view.showdebug = false;
8863 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8865 R_ResetViewRendering3D();
8867 R_ClearScreen(r_refdef.fogenabled);
8868 if (r_timereport_active)
8869 R_TimeReport("HDRclear");
8872 if (r_timereport_active)
8873 R_TimeReport("visibility");
8875 // only do secondary renders with HDR if r_hdr is 2 or higher
8876 r_waterstate.numwaterplanes = 0;
8877 if (r_waterstate.enabled && r_hdr.integer >= 2)
8878 R_RenderWaterPlanes();
8880 r_refdef.view.showdebug = true;
8882 r_waterstate.numwaterplanes = 0;
8884 R_ResetViewRendering2D();
8886 R_Bloom_CopyHDRTexture();
8887 R_Bloom_MakeTexture();
8889 // restore the view settings
8890 r_refdef.view.width = oldwidth;
8891 r_refdef.view.height = oldheight;
8892 r_refdef.view.colorscale = oldcolorscale;
8894 R_ResetViewRendering3D();
8896 R_ClearScreen(r_refdef.fogenabled);
8897 if (r_timereport_active)
8898 R_TimeReport("viewclear");
8901 static void R_BlendView(void)
8903 unsigned int permutation;
8904 float uservecs[4][4];
8906 switch (vid.renderpath)
8908 case RENDERPATH_GL20:
8909 case RENDERPATH_CGGL:
8910 case RENDERPATH_D3D9:
8911 case RENDERPATH_D3D10:
8912 case RENDERPATH_D3D11:
8914 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8915 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8916 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8917 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8918 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8920 if (r_bloomstate.texture_screen)
8922 // make sure the buffer is available
8923 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8925 R_ResetViewRendering2D();
8927 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8929 // declare variables
8931 static float avgspeed;
8933 speed = VectorLength(cl.movement_velocity);
8935 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8936 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8938 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8939 speed = bound(0, speed, 1);
8940 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8942 // calculate values into a standard alpha
8943 cl.motionbluralpha = 1 - exp(-
8945 (r_motionblur.value * speed / 80)
8947 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8950 max(0.0001, cl.time - cl.oldtime) // fps independent
8953 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8954 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8956 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8958 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8959 GL_Color(1, 1, 1, cl.motionbluralpha);
8960 switch(vid.renderpath)
8962 case RENDERPATH_GL11:
8963 case RENDERPATH_GL13:
8964 case RENDERPATH_GL20:
8965 case RENDERPATH_CGGL:
8966 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8968 case RENDERPATH_D3D9:
8969 case RENDERPATH_D3D10:
8970 case RENDERPATH_D3D11:
8971 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8974 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8975 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8976 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8980 // copy view into the screen texture
8981 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);
8982 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8984 else if (!r_bloomstate.texture_bloom)
8986 // we may still have to do view tint...
8987 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8989 // apply a color tint to the whole view
8990 R_ResetViewRendering2D();
8991 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8992 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8993 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8994 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8995 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8997 break; // no screen processing, no bloom, skip it
9000 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9002 // render simple bloom effect
9003 // copy the screen and shrink it and darken it for the bloom process
9004 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9005 // make the bloom texture
9006 R_Bloom_MakeTexture();
9009 #if _MSC_VER >= 1400
9010 #define sscanf sscanf_s
9012 memset(uservecs, 0, sizeof(uservecs));
9013 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9014 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9015 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9016 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9018 R_ResetViewRendering2D();
9019 GL_Color(1, 1, 1, 1);
9020 GL_BlendFunc(GL_ONE, GL_ZERO);
9022 switch(vid.renderpath)
9024 case RENDERPATH_GL20:
9025 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9026 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9027 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9028 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9029 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9030 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]);
9031 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9032 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]);
9033 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]);
9034 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]);
9035 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]);
9036 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9037 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9038 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);
9040 case RENDERPATH_CGGL:
9042 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9043 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9044 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9045 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9046 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9047 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
9048 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9049 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
9050 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
9051 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
9052 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
9053 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9054 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9055 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);
9058 case RENDERPATH_D3D9:
9060 // 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...
9061 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9062 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9063 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9064 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9065 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9066 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9067 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9068 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9069 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9070 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9071 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9072 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9073 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9074 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9077 case RENDERPATH_D3D10:
9078 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9080 case RENDERPATH_D3D11:
9081 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9086 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9087 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9089 case RENDERPATH_GL13:
9090 case RENDERPATH_GL11:
9091 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9093 // apply a color tint to the whole view
9094 R_ResetViewRendering2D();
9095 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9096 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9097 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9098 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9099 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9105 matrix4x4_t r_waterscrollmatrix;
9107 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9109 if (r_refdef.fog_density)
9111 r_refdef.fogcolor[0] = r_refdef.fog_red;
9112 r_refdef.fogcolor[1] = r_refdef.fog_green;
9113 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9115 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9116 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9117 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9118 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9122 VectorCopy(r_refdef.fogcolor, fogvec);
9123 // color.rgb *= ContrastBoost * SceneBrightness;
9124 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9125 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9126 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9127 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9132 void R_UpdateVariables(void)
9136 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9138 r_refdef.farclip = r_farclip_base.value;
9139 if (r_refdef.scene.worldmodel)
9140 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9141 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9143 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9144 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9145 r_refdef.polygonfactor = 0;
9146 r_refdef.polygonoffset = 0;
9147 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9148 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9150 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9151 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9152 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9153 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9154 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9155 if (r_showsurfaces.integer)
9157 r_refdef.scene.rtworld = false;
9158 r_refdef.scene.rtworldshadows = false;
9159 r_refdef.scene.rtdlight = false;
9160 r_refdef.scene.rtdlightshadows = false;
9161 r_refdef.lightmapintensity = 0;
9164 if (gamemode == GAME_NEHAHRA)
9166 if (gl_fogenable.integer)
9168 r_refdef.oldgl_fogenable = true;
9169 r_refdef.fog_density = gl_fogdensity.value;
9170 r_refdef.fog_red = gl_fogred.value;
9171 r_refdef.fog_green = gl_foggreen.value;
9172 r_refdef.fog_blue = gl_fogblue.value;
9173 r_refdef.fog_alpha = 1;
9174 r_refdef.fog_start = 0;
9175 r_refdef.fog_end = gl_skyclip.value;
9176 r_refdef.fog_height = 1<<30;
9177 r_refdef.fog_fadedepth = 128;
9179 else if (r_refdef.oldgl_fogenable)
9181 r_refdef.oldgl_fogenable = false;
9182 r_refdef.fog_density = 0;
9183 r_refdef.fog_red = 0;
9184 r_refdef.fog_green = 0;
9185 r_refdef.fog_blue = 0;
9186 r_refdef.fog_alpha = 0;
9187 r_refdef.fog_start = 0;
9188 r_refdef.fog_end = 0;
9189 r_refdef.fog_height = 1<<30;
9190 r_refdef.fog_fadedepth = 128;
9194 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9195 r_refdef.fog_start = max(0, r_refdef.fog_start);
9196 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9198 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9200 if (r_refdef.fog_density && r_drawfog.integer)
9202 r_refdef.fogenabled = true;
9203 // this is the point where the fog reaches 0.9986 alpha, which we
9204 // consider a good enough cutoff point for the texture
9205 // (0.9986 * 256 == 255.6)
9206 if (r_fog_exp2.integer)
9207 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9209 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9210 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9211 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9212 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9213 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9214 R_BuildFogHeightTexture();
9215 // fog color was already set
9216 // update the fog texture
9217 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)
9218 R_BuildFogTexture();
9219 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9220 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9223 r_refdef.fogenabled = false;
9225 switch(vid.renderpath)
9227 case RENDERPATH_GL20:
9228 case RENDERPATH_CGGL:
9229 case RENDERPATH_D3D9:
9230 case RENDERPATH_D3D10:
9231 case RENDERPATH_D3D11:
9232 if(v_glslgamma.integer && !vid_gammatables_trivial)
9234 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9236 // build GLSL gamma texture
9237 #define RAMPWIDTH 256
9238 unsigned short ramp[RAMPWIDTH * 3];
9239 unsigned char rampbgr[RAMPWIDTH][4];
9242 r_texture_gammaramps_serial = vid_gammatables_serial;
9244 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9245 for(i = 0; i < RAMPWIDTH; ++i)
9247 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9248 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9249 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9252 if (r_texture_gammaramps)
9254 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9258 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9264 // remove GLSL gamma texture
9267 case RENDERPATH_GL13:
9268 case RENDERPATH_GL11:
9273 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9274 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9280 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9281 if( scenetype != r_currentscenetype ) {
9282 // store the old scenetype
9283 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9284 r_currentscenetype = scenetype;
9285 // move in the new scene
9286 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9295 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9297 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9298 if( scenetype == r_currentscenetype ) {
9299 return &r_refdef.scene;
9301 return &r_scenes_store[ scenetype ];
9310 void R_RenderView(void)
9312 if (r_timereport_active)
9313 R_TimeReport("start");
9314 r_textureframe++; // used only by R_GetCurrentTexture
9315 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9317 if (!r_drawentities.integer)
9318 r_refdef.scene.numentities = 0;
9320 R_AnimCache_ClearCache();
9321 R_FrameData_NewFrame();
9323 if (r_refdef.view.isoverlay)
9325 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9326 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9327 R_TimeReport("depthclear");
9329 r_refdef.view.showdebug = false;
9331 r_waterstate.enabled = false;
9332 r_waterstate.numwaterplanes = 0;
9340 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9341 return; //Host_Error ("R_RenderView: NULL worldmodel");
9343 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9345 R_RenderView_UpdateViewVectors();
9347 R_Shadow_UpdateWorldLightSelection();
9349 R_Bloom_StartFrame();
9350 R_Water_StartFrame();
9353 if (r_timereport_active)
9354 R_TimeReport("viewsetup");
9356 R_ResetViewRendering3D();
9358 if (r_refdef.view.clear || r_refdef.fogenabled)
9360 R_ClearScreen(r_refdef.fogenabled);
9361 if (r_timereport_active)
9362 R_TimeReport("viewclear");
9364 r_refdef.view.clear = true;
9366 // this produces a bloom texture to be used in R_BlendView() later
9367 if (r_hdr.integer && r_bloomstate.bloomwidth)
9369 R_HDR_RenderBloomTexture();
9370 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9371 r_textureframe++; // used only by R_GetCurrentTexture
9374 r_refdef.view.showdebug = true;
9377 if (r_timereport_active)
9378 R_TimeReport("visibility");
9380 r_waterstate.numwaterplanes = 0;
9381 if (r_waterstate.enabled)
9382 R_RenderWaterPlanes();
9385 r_waterstate.numwaterplanes = 0;
9388 if (r_timereport_active)
9389 R_TimeReport("blendview");
9391 GL_Scissor(0, 0, vid.width, vid.height);
9392 GL_ScissorTest(false);
9396 void R_RenderWaterPlanes(void)
9398 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9400 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9401 if (r_timereport_active)
9402 R_TimeReport("waterworld");
9405 // don't let sound skip if going slow
9406 if (r_refdef.scene.extraupdate)
9409 R_DrawModelsAddWaterPlanes();
9410 if (r_timereport_active)
9411 R_TimeReport("watermodels");
9413 if (r_waterstate.numwaterplanes)
9415 R_Water_ProcessPlanes();
9416 if (r_timereport_active)
9417 R_TimeReport("waterscenes");
9421 extern void R_DrawLightningBeams (void);
9422 extern void VM_CL_AddPolygonsToMeshQueue (void);
9423 extern void R_DrawPortals (void);
9424 extern cvar_t cl_locs_show;
9425 static void R_DrawLocs(void);
9426 static void R_DrawEntityBBoxes(void);
9427 static void R_DrawModelDecals(void);
9428 extern void R_DrawModelShadows(void);
9429 extern void R_DrawModelShadowMaps(void);
9430 extern cvar_t cl_decals_newsystem;
9431 extern qboolean r_shadow_usingdeferredprepass;
9432 void R_RenderScene(void)
9434 qboolean shadowmapping = false;
9436 if (r_timereport_active)
9437 R_TimeReport("beginscene");
9439 r_refdef.stats.renders++;
9443 // don't let sound skip if going slow
9444 if (r_refdef.scene.extraupdate)
9447 R_MeshQueue_BeginScene();
9451 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);
9453 if (r_timereport_active)
9454 R_TimeReport("skystartframe");
9456 if (cl.csqc_vidvars.drawworld)
9458 // don't let sound skip if going slow
9459 if (r_refdef.scene.extraupdate)
9462 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9464 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9465 if (r_timereport_active)
9466 R_TimeReport("worldsky");
9469 if (R_DrawBrushModelsSky() && r_timereport_active)
9470 R_TimeReport("bmodelsky");
9472 if (skyrendermasked && skyrenderlater)
9474 // we have to force off the water clipping plane while rendering sky
9478 if (r_timereport_active)
9479 R_TimeReport("sky");
9483 R_AnimCache_CacheVisibleEntities();
9484 if (r_timereport_active)
9485 R_TimeReport("animation");
9487 R_Shadow_PrepareLights();
9488 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9489 R_Shadow_PrepareModelShadows();
9490 if (r_timereport_active)
9491 R_TimeReport("preparelights");
9493 if (R_Shadow_ShadowMappingEnabled())
9494 shadowmapping = true;
9496 if (r_shadow_usingdeferredprepass)
9497 R_Shadow_DrawPrepass();
9499 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9501 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9502 if (r_timereport_active)
9503 R_TimeReport("worlddepth");
9505 if (r_depthfirst.integer >= 2)
9507 R_DrawModelsDepth();
9508 if (r_timereport_active)
9509 R_TimeReport("modeldepth");
9512 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9514 R_DrawModelShadowMaps();
9515 R_ResetViewRendering3D();
9516 // don't let sound skip if going slow
9517 if (r_refdef.scene.extraupdate)
9521 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9523 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9524 if (r_timereport_active)
9525 R_TimeReport("world");
9528 // don't let sound skip if going slow
9529 if (r_refdef.scene.extraupdate)
9533 if (r_timereport_active)
9534 R_TimeReport("models");
9536 // don't let sound skip if going slow
9537 if (r_refdef.scene.extraupdate)
9540 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9542 R_DrawModelShadows();
9543 R_ResetViewRendering3D();
9544 // don't let sound skip if going slow
9545 if (r_refdef.scene.extraupdate)
9549 if (!r_shadow_usingdeferredprepass)
9551 R_Shadow_DrawLights();
9552 if (r_timereport_active)
9553 R_TimeReport("rtlights");
9556 // don't let sound skip if going slow
9557 if (r_refdef.scene.extraupdate)
9560 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9562 R_DrawModelShadows();
9563 R_ResetViewRendering3D();
9564 // don't let sound skip if going slow
9565 if (r_refdef.scene.extraupdate)
9569 if (cl.csqc_vidvars.drawworld)
9571 if (cl_decals_newsystem.integer)
9573 R_DrawModelDecals();
9574 if (r_timereport_active)
9575 R_TimeReport("modeldecals");
9580 if (r_timereport_active)
9581 R_TimeReport("decals");
9585 if (r_timereport_active)
9586 R_TimeReport("particles");
9589 if (r_timereport_active)
9590 R_TimeReport("explosions");
9592 R_DrawLightningBeams();
9593 if (r_timereport_active)
9594 R_TimeReport("lightning");
9597 VM_CL_AddPolygonsToMeshQueue();
9599 if (r_refdef.view.showdebug)
9601 if (cl_locs_show.integer)
9604 if (r_timereport_active)
9605 R_TimeReport("showlocs");
9608 if (r_drawportals.integer)
9611 if (r_timereport_active)
9612 R_TimeReport("portals");
9615 if (r_showbboxes.value > 0)
9617 R_DrawEntityBBoxes();
9618 if (r_timereport_active)
9619 R_TimeReport("bboxes");
9623 R_MeshQueue_RenderTransparent();
9624 if (r_timereport_active)
9625 R_TimeReport("drawtrans");
9627 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))
9629 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9630 if (r_timereport_active)
9631 R_TimeReport("worlddebug");
9632 R_DrawModelsDebug();
9633 if (r_timereport_active)
9634 R_TimeReport("modeldebug");
9637 if (cl.csqc_vidvars.drawworld)
9639 R_Shadow_DrawCoronas();
9640 if (r_timereport_active)
9641 R_TimeReport("coronas");
9644 // don't let sound skip if going slow
9645 if (r_refdef.scene.extraupdate)
9648 R_ResetViewRendering2D();
9651 static const unsigned short bboxelements[36] =
9661 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9664 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9666 RSurf_ActiveWorldEntity();
9668 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9669 GL_DepthMask(false);
9670 GL_DepthRange(0, 1);
9671 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9672 R_Mesh_ResetTextureState();
9674 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9675 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9676 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9677 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9678 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9679 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9680 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9681 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9682 R_FillColors(color4f, 8, cr, cg, cb, ca);
9683 if (r_refdef.fogenabled)
9685 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9687 f1 = RSurf_FogVertex(v);
9689 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9690 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9691 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9694 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9695 R_Mesh_ResetTextureState();
9696 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9697 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9700 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9704 prvm_edict_t *edict;
9705 prvm_prog_t *prog_save = prog;
9707 // this function draws bounding boxes of server entities
9711 GL_CullFace(GL_NONE);
9712 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9716 for (i = 0;i < numsurfaces;i++)
9718 edict = PRVM_EDICT_NUM(surfacelist[i]);
9719 switch ((int)edict->fields.server->solid)
9721 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
9722 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
9723 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
9724 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9725 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
9726 default: Vector4Set(color, 0, 0, 0, 0.50);break;
9728 color[3] *= r_showbboxes.value;
9729 color[3] = bound(0, color[3], 1);
9730 GL_DepthTest(!r_showdisabledepthtest.integer);
9731 GL_CullFace(r_refdef.view.cullface_front);
9732 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9738 static void R_DrawEntityBBoxes(void)
9741 prvm_edict_t *edict;
9743 prvm_prog_t *prog_save = prog;
9745 // this function draws bounding boxes of server entities
9751 for (i = 0;i < prog->num_edicts;i++)
9753 edict = PRVM_EDICT_NUM(i);
9754 if (edict->priv.server->free)
9756 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9757 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9759 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9761 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9762 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9768 static const int nomodelelement3i[24] =
9780 static const unsigned short nomodelelement3s[24] =
9792 static const float nomodelvertex3f[6*3] =
9802 static const float nomodelcolor4f[6*4] =
9804 0.0f, 0.0f, 0.5f, 1.0f,
9805 0.0f, 0.0f, 0.5f, 1.0f,
9806 0.0f, 0.5f, 0.0f, 1.0f,
9807 0.0f, 0.5f, 0.0f, 1.0f,
9808 0.5f, 0.0f, 0.0f, 1.0f,
9809 0.5f, 0.0f, 0.0f, 1.0f
9812 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9818 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);
9820 // this is only called once per entity so numsurfaces is always 1, and
9821 // surfacelist is always {0}, so this code does not handle batches
9823 if (rsurface.ent_flags & RENDER_ADDITIVE)
9825 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9826 GL_DepthMask(false);
9828 else if (rsurface.colormod[3] < 1)
9830 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9831 GL_DepthMask(false);
9835 GL_BlendFunc(GL_ONE, GL_ZERO);
9838 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9839 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9840 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9841 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9842 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9843 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9844 for (i = 0, c = color4f;i < 6;i++, c += 4)
9846 c[0] *= rsurface.colormod[0];
9847 c[1] *= rsurface.colormod[1];
9848 c[2] *= rsurface.colormod[2];
9849 c[3] *= rsurface.colormod[3];
9851 if (r_refdef.fogenabled)
9853 for (i = 0, c = color4f;i < 6;i++, c += 4)
9855 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9857 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9858 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9859 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9862 R_Mesh_ResetTextureState();
9863 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9864 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9867 void R_DrawNoModel(entity_render_t *ent)
9870 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9871 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9872 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9874 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9877 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9879 vec3_t right1, right2, diff, normal;
9881 VectorSubtract (org2, org1, normal);
9883 // calculate 'right' vector for start
9884 VectorSubtract (r_refdef.view.origin, org1, diff);
9885 CrossProduct (normal, diff, right1);
9886 VectorNormalize (right1);
9888 // calculate 'right' vector for end
9889 VectorSubtract (r_refdef.view.origin, org2, diff);
9890 CrossProduct (normal, diff, right2);
9891 VectorNormalize (right2);
9893 vert[ 0] = org1[0] + width * right1[0];
9894 vert[ 1] = org1[1] + width * right1[1];
9895 vert[ 2] = org1[2] + width * right1[2];
9896 vert[ 3] = org1[0] - width * right1[0];
9897 vert[ 4] = org1[1] - width * right1[1];
9898 vert[ 5] = org1[2] - width * right1[2];
9899 vert[ 6] = org2[0] - width * right2[0];
9900 vert[ 7] = org2[1] - width * right2[1];
9901 vert[ 8] = org2[2] - width * right2[2];
9902 vert[ 9] = org2[0] + width * right2[0];
9903 vert[10] = org2[1] + width * right2[1];
9904 vert[11] = org2[2] + width * right2[2];
9907 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)
9909 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9910 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9911 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9912 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9913 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9914 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9915 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9916 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9917 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9918 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9919 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9920 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9923 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9928 VectorSet(v, x, y, z);
9929 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9930 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9932 if (i == mesh->numvertices)
9934 if (mesh->numvertices < mesh->maxvertices)
9936 VectorCopy(v, vertex3f);
9937 mesh->numvertices++;
9939 return mesh->numvertices;
9945 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9949 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9950 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9951 e = mesh->element3i + mesh->numtriangles * 3;
9952 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9954 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9955 if (mesh->numtriangles < mesh->maxtriangles)
9960 mesh->numtriangles++;
9962 element[1] = element[2];
9966 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9970 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9971 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9972 e = mesh->element3i + mesh->numtriangles * 3;
9973 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9975 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9976 if (mesh->numtriangles < mesh->maxtriangles)
9981 mesh->numtriangles++;
9983 element[1] = element[2];
9987 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9988 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9990 int planenum, planenum2;
9993 mplane_t *plane, *plane2;
9995 double temppoints[2][256*3];
9996 // figure out how large a bounding box we need to properly compute this brush
9998 for (w = 0;w < numplanes;w++)
9999 maxdist = max(maxdist, fabs(planes[w].dist));
10000 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10001 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10002 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10006 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10007 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10009 if (planenum2 == planenum)
10011 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);
10014 if (tempnumpoints < 3)
10016 // generate elements forming a triangle fan for this polygon
10017 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10021 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)
10023 texturelayer_t *layer;
10024 layer = t->currentlayers + t->currentnumlayers++;
10025 layer->type = type;
10026 layer->depthmask = depthmask;
10027 layer->blendfunc1 = blendfunc1;
10028 layer->blendfunc2 = blendfunc2;
10029 layer->texture = texture;
10030 layer->texmatrix = *matrix;
10031 layer->color[0] = r;
10032 layer->color[1] = g;
10033 layer->color[2] = b;
10034 layer->color[3] = a;
10037 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10039 if(parms[0] == 0 && parms[1] == 0)
10041 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10042 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10047 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10050 index = parms[2] + r_refdef.scene.time * parms[3];
10051 index -= floor(index);
10052 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10055 case Q3WAVEFUNC_NONE:
10056 case Q3WAVEFUNC_NOISE:
10057 case Q3WAVEFUNC_COUNT:
10060 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10061 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10062 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10063 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10064 case Q3WAVEFUNC_TRIANGLE:
10066 f = index - floor(index);
10069 else if (index < 2)
10071 else if (index < 3)
10077 f = parms[0] + parms[1] * f;
10078 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10079 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10083 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10088 matrix4x4_t matrix, temp;
10089 switch(tcmod->tcmod)
10091 case Q3TCMOD_COUNT:
10093 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10094 matrix = r_waterscrollmatrix;
10096 matrix = identitymatrix;
10098 case Q3TCMOD_ENTITYTRANSLATE:
10099 // this is used in Q3 to allow the gamecode to control texcoord
10100 // scrolling on the entity, which is not supported in darkplaces yet.
10101 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10103 case Q3TCMOD_ROTATE:
10104 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10105 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10106 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10108 case Q3TCMOD_SCALE:
10109 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10111 case Q3TCMOD_SCROLL:
10112 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10114 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10115 w = (int) tcmod->parms[0];
10116 h = (int) tcmod->parms[1];
10117 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10119 idx = (int) floor(f * w * h);
10120 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10122 case Q3TCMOD_STRETCH:
10123 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10124 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10126 case Q3TCMOD_TRANSFORM:
10127 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10128 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10129 VectorSet(tcmat + 6, 0 , 0 , 1);
10130 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10131 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10133 case Q3TCMOD_TURBULENT:
10134 // this is handled in the RSurf_PrepareVertices function
10135 matrix = identitymatrix;
10139 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10142 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10144 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10145 char name[MAX_QPATH];
10146 skinframe_t *skinframe;
10147 unsigned char pixels[296*194];
10148 strlcpy(cache->name, skinname, sizeof(cache->name));
10149 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10150 if (developer_loading.integer)
10151 Con_Printf("loading %s\n", name);
10152 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10153 if (!skinframe || !skinframe->base)
10156 fs_offset_t filesize;
10158 f = FS_LoadFile(name, tempmempool, true, &filesize);
10161 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10162 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10166 cache->skinframe = skinframe;
10169 texture_t *R_GetCurrentTexture(texture_t *t)
10172 const entity_render_t *ent = rsurface.entity;
10173 dp_model_t *model = ent->model;
10174 q3shaderinfo_layer_tcmod_t *tcmod;
10176 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10177 return t->currentframe;
10178 t->update_lastrenderframe = r_textureframe;
10179 t->update_lastrenderentity = (void *)ent;
10181 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10182 t->camera_entity = ent->entitynumber;
10184 t->camera_entity = 0;
10186 // switch to an alternate material if this is a q1bsp animated material
10188 texture_t *texture = t;
10189 int s = rsurface.ent_skinnum;
10190 if ((unsigned int)s >= (unsigned int)model->numskins)
10192 if (model->skinscenes)
10194 if (model->skinscenes[s].framecount > 1)
10195 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10197 s = model->skinscenes[s].firstframe;
10200 t = t + s * model->num_surfaces;
10203 // use an alternate animation if the entity's frame is not 0,
10204 // and only if the texture has an alternate animation
10205 if (rsurface.ent_alttextures && t->anim_total[1])
10206 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10208 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10210 texture->currentframe = t;
10213 // update currentskinframe to be a qw skin or animation frame
10214 if (rsurface.ent_qwskin >= 0)
10216 i = rsurface.ent_qwskin;
10217 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10219 r_qwskincache_size = cl.maxclients;
10221 Mem_Free(r_qwskincache);
10222 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10224 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10225 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10226 t->currentskinframe = r_qwskincache[i].skinframe;
10227 if (t->currentskinframe == NULL)
10228 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10230 else if (t->numskinframes >= 2)
10231 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10232 if (t->backgroundnumskinframes >= 2)
10233 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10235 t->currentmaterialflags = t->basematerialflags;
10236 t->currentalpha = rsurface.colormod[3];
10237 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10238 t->currentalpha *= r_wateralpha.value;
10239 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10240 t->currentalpha *= t->r_water_wateralpha;
10241 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10242 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10243 if (!(rsurface.ent_flags & RENDER_LIGHT))
10244 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10245 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10247 // pick a model lighting mode
10248 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10249 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10251 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10253 if (rsurface.ent_flags & RENDER_ADDITIVE)
10254 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10255 else if (t->currentalpha < 1)
10256 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10257 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10258 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10259 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10260 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10261 if (t->backgroundnumskinframes)
10262 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10263 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10265 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10266 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10269 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10270 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10271 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10273 // there is no tcmod
10274 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10276 t->currenttexmatrix = r_waterscrollmatrix;
10277 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10279 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10281 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10282 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10285 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10286 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10287 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10288 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10290 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10291 if (t->currentskinframe->qpixels)
10292 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10293 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10294 if (!t->basetexture)
10295 t->basetexture = r_texture_notexture;
10296 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10297 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10298 t->nmaptexture = t->currentskinframe->nmap;
10299 if (!t->nmaptexture)
10300 t->nmaptexture = r_texture_blanknormalmap;
10301 t->glosstexture = r_texture_black;
10302 t->glowtexture = t->currentskinframe->glow;
10303 t->fogtexture = t->currentskinframe->fog;
10304 t->reflectmasktexture = t->currentskinframe->reflect;
10305 if (t->backgroundnumskinframes)
10307 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10308 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10309 t->backgroundglosstexture = r_texture_black;
10310 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10311 if (!t->backgroundnmaptexture)
10312 t->backgroundnmaptexture = r_texture_blanknormalmap;
10316 t->backgroundbasetexture = r_texture_white;
10317 t->backgroundnmaptexture = r_texture_blanknormalmap;
10318 t->backgroundglosstexture = r_texture_black;
10319 t->backgroundglowtexture = NULL;
10321 t->specularpower = r_shadow_glossexponent.value;
10322 // TODO: store reference values for these in the texture?
10323 t->specularscale = 0;
10324 if (r_shadow_gloss.integer > 0)
10326 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10328 if (r_shadow_glossintensity.value > 0)
10330 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10331 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10332 t->specularscale = r_shadow_glossintensity.value;
10335 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10337 t->glosstexture = r_texture_white;
10338 t->backgroundglosstexture = r_texture_white;
10339 t->specularscale = r_shadow_gloss2intensity.value;
10340 t->specularpower = r_shadow_gloss2exponent.value;
10343 t->specularscale *= t->specularscalemod;
10344 t->specularpower *= t->specularpowermod;
10346 // lightmaps mode looks bad with dlights using actual texturing, so turn
10347 // off the colormap and glossmap, but leave the normalmap on as it still
10348 // accurately represents the shading involved
10349 if (gl_lightmaps.integer)
10351 t->basetexture = r_texture_grey128;
10352 t->pantstexture = r_texture_black;
10353 t->shirttexture = r_texture_black;
10354 t->nmaptexture = r_texture_blanknormalmap;
10355 t->glosstexture = r_texture_black;
10356 t->glowtexture = NULL;
10357 t->fogtexture = NULL;
10358 t->reflectmasktexture = NULL;
10359 t->backgroundbasetexture = NULL;
10360 t->backgroundnmaptexture = r_texture_blanknormalmap;
10361 t->backgroundglosstexture = r_texture_black;
10362 t->backgroundglowtexture = NULL;
10363 t->specularscale = 0;
10364 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10367 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10368 VectorClear(t->dlightcolor);
10369 t->currentnumlayers = 0;
10370 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10372 int blendfunc1, blendfunc2;
10373 qboolean depthmask;
10374 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10376 blendfunc1 = GL_SRC_ALPHA;
10377 blendfunc2 = GL_ONE;
10379 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10381 blendfunc1 = GL_SRC_ALPHA;
10382 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10384 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10386 blendfunc1 = t->customblendfunc[0];
10387 blendfunc2 = t->customblendfunc[1];
10391 blendfunc1 = GL_ONE;
10392 blendfunc2 = GL_ZERO;
10394 // don't colormod evilblend textures
10395 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10396 VectorSet(t->lightmapcolor, 1, 1, 1);
10397 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10398 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10400 // fullbright is not affected by r_refdef.lightmapintensity
10401 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]);
10402 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10403 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]);
10404 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10405 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]);
10409 vec3_t ambientcolor;
10411 // set the color tint used for lights affecting this surface
10412 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10414 // q3bsp has no lightmap updates, so the lightstylevalue that
10415 // would normally be baked into the lightmap must be
10416 // applied to the color
10417 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10418 if (model->type == mod_brushq3)
10419 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10420 colorscale *= r_refdef.lightmapintensity;
10421 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10422 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10423 // basic lit geometry
10424 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]);
10425 // add pants/shirt if needed
10426 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10427 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]);
10428 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10429 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]);
10430 // now add ambient passes if needed
10431 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10433 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]);
10434 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10435 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]);
10436 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10437 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]);
10440 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10441 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]);
10442 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10444 // if this is opaque use alpha blend which will darken the earlier
10447 // if this is an alpha blended material, all the earlier passes
10448 // were darkened by fog already, so we only need to add the fog
10449 // color ontop through the fog mask texture
10451 // if this is an additive blended material, all the earlier passes
10452 // were darkened by fog already, and we should not add fog color
10453 // (because the background was not darkened, there is no fog color
10454 // that was lost behind it).
10455 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]);
10459 return t->currentframe;
10462 rsurfacestate_t rsurface;
10464 void R_Mesh_ResizeArrays(int newvertices)
10466 unsigned char *base;
10468 if (rsurface.array_size >= newvertices)
10470 if (rsurface.array_base)
10471 Mem_Free(rsurface.array_base);
10472 rsurface.array_size = (newvertices + 1023) & ~1023;
10474 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10475 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10476 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10477 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10478 size += rsurface.array_size * sizeof(float[3]);
10479 size += rsurface.array_size * sizeof(float[3]);
10480 size += rsurface.array_size * sizeof(float[3]);
10481 size += rsurface.array_size * sizeof(float[3]);
10482 size += rsurface.array_size * sizeof(float[3]);
10483 size += rsurface.array_size * sizeof(float[3]);
10484 size += rsurface.array_size * sizeof(float[3]);
10485 size += rsurface.array_size * sizeof(float[3]);
10486 size += rsurface.array_size * sizeof(float[4]);
10487 size += rsurface.array_size * sizeof(float[2]);
10488 size += rsurface.array_size * sizeof(float[2]);
10489 size += rsurface.array_size * sizeof(float[4]);
10490 size += rsurface.array_size * sizeof(int[3]);
10491 size += rsurface.array_size * sizeof(unsigned short[3]);
10492 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10493 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10494 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10495 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10496 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10497 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10498 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10499 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10500 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10501 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10502 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10503 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10504 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10505 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10506 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10507 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10508 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10509 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10510 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10513 void RSurf_ActiveWorldEntity(void)
10515 dp_model_t *model = r_refdef.scene.worldmodel;
10516 //if (rsurface.entity == r_refdef.scene.worldentity)
10518 rsurface.entity = r_refdef.scene.worldentity;
10519 rsurface.skeleton = NULL;
10520 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10521 rsurface.ent_skinnum = 0;
10522 rsurface.ent_qwskin = -1;
10523 rsurface.ent_shadertime = 0;
10524 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10525 if (rsurface.array_size < model->surfmesh.num_vertices)
10526 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10527 rsurface.matrix = identitymatrix;
10528 rsurface.inversematrix = identitymatrix;
10529 rsurface.matrixscale = 1;
10530 rsurface.inversematrixscale = 1;
10531 R_EntityMatrix(&identitymatrix);
10532 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10533 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10534 rsurface.fograngerecip = r_refdef.fograngerecip;
10535 rsurface.fogheightfade = r_refdef.fogheightfade;
10536 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10537 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10538 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10539 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10540 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10541 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10542 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10543 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10544 rsurface.colormod[3] = 1;
10545 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);
10546 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10547 rsurface.frameblend[0].lerp = 1;
10548 rsurface.ent_alttextures = false;
10549 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10550 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10551 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10552 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10553 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10554 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10555 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10556 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10557 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10558 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10559 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10560 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10561 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10562 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10563 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10564 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10565 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10566 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10567 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10568 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10569 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10570 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10571 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10572 rsurface.modelelement3i = model->surfmesh.data_element3i;
10573 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10574 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10575 rsurface.modelelement3s = model->surfmesh.data_element3s;
10576 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10577 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10578 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10579 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10580 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10581 rsurface.modelsurfaces = model->data_surfaces;
10582 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10583 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10584 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10585 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10586 rsurface.modelgeneratedvertex = false;
10587 rsurface.batchgeneratedvertex = false;
10588 rsurface.batchfirstvertex = 0;
10589 rsurface.batchnumvertices = 0;
10590 rsurface.batchfirsttriangle = 0;
10591 rsurface.batchnumtriangles = 0;
10592 rsurface.batchvertex3f = NULL;
10593 rsurface.batchvertex3f_vertexbuffer = NULL;
10594 rsurface.batchvertex3f_bufferoffset = 0;
10595 rsurface.batchsvector3f = NULL;
10596 rsurface.batchsvector3f_vertexbuffer = NULL;
10597 rsurface.batchsvector3f_bufferoffset = 0;
10598 rsurface.batchtvector3f = NULL;
10599 rsurface.batchtvector3f_vertexbuffer = NULL;
10600 rsurface.batchtvector3f_bufferoffset = 0;
10601 rsurface.batchnormal3f = NULL;
10602 rsurface.batchnormal3f_vertexbuffer = NULL;
10603 rsurface.batchnormal3f_bufferoffset = 0;
10604 rsurface.batchlightmapcolor4f = NULL;
10605 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10606 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10607 rsurface.batchtexcoordtexture2f = NULL;
10608 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10609 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10610 rsurface.batchtexcoordlightmap2f = NULL;
10611 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10612 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10613 rsurface.batchvertexmesh = NULL;
10614 rsurface.batchvertexmeshbuffer = NULL;
10615 rsurface.batchvertexposition = NULL;
10616 rsurface.batchvertexpositionbuffer = NULL;
10617 rsurface.batchelement3i = NULL;
10618 rsurface.batchelement3i_indexbuffer = NULL;
10619 rsurface.batchelement3i_bufferoffset = 0;
10620 rsurface.batchelement3s = NULL;
10621 rsurface.batchelement3s_indexbuffer = NULL;
10622 rsurface.batchelement3s_bufferoffset = 0;
10623 rsurface.passcolor4f = NULL;
10624 rsurface.passcolor4f_vertexbuffer = NULL;
10625 rsurface.passcolor4f_bufferoffset = 0;
10628 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10630 dp_model_t *model = ent->model;
10631 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10633 rsurface.entity = (entity_render_t *)ent;
10634 rsurface.skeleton = ent->skeleton;
10635 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10636 rsurface.ent_skinnum = ent->skinnum;
10637 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;
10638 rsurface.ent_shadertime = ent->shadertime;
10639 rsurface.ent_flags = ent->flags;
10640 if (rsurface.array_size < model->surfmesh.num_vertices)
10641 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10642 rsurface.matrix = ent->matrix;
10643 rsurface.inversematrix = ent->inversematrix;
10644 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10645 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10646 R_EntityMatrix(&rsurface.matrix);
10647 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10648 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10649 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10650 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10651 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10652 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10653 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10654 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10655 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10656 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10657 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10658 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10659 rsurface.colormod[3] = ent->alpha;
10660 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10661 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10662 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10663 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10664 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10665 if (ent->model->brush.submodel && !prepass)
10667 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10668 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10670 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10672 if (ent->animcache_vertex3f && !r_framedata_failed)
10674 rsurface.modelvertex3f = ent->animcache_vertex3f;
10675 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10676 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10677 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10678 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10679 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10680 rsurface.modelvertexposition = ent->animcache_vertexposition;
10681 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10683 else if (wanttangents)
10685 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10686 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10687 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10688 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10689 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10690 rsurface.modelvertexmesh = NULL;
10691 rsurface.modelvertexmeshbuffer = NULL;
10692 rsurface.modelvertexposition = NULL;
10693 rsurface.modelvertexpositionbuffer = NULL;
10695 else if (wantnormals)
10697 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10698 rsurface.modelsvector3f = NULL;
10699 rsurface.modeltvector3f = NULL;
10700 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10701 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10702 rsurface.modelvertexmesh = NULL;
10703 rsurface.modelvertexmeshbuffer = NULL;
10704 rsurface.modelvertexposition = NULL;
10705 rsurface.modelvertexpositionbuffer = NULL;
10709 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10710 rsurface.modelsvector3f = NULL;
10711 rsurface.modeltvector3f = NULL;
10712 rsurface.modelnormal3f = NULL;
10713 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10714 rsurface.modelvertexmesh = NULL;
10715 rsurface.modelvertexmeshbuffer = NULL;
10716 rsurface.modelvertexposition = NULL;
10717 rsurface.modelvertexpositionbuffer = NULL;
10719 rsurface.modelvertex3f_vertexbuffer = 0;
10720 rsurface.modelvertex3f_bufferoffset = 0;
10721 rsurface.modelsvector3f_vertexbuffer = 0;
10722 rsurface.modelsvector3f_bufferoffset = 0;
10723 rsurface.modeltvector3f_vertexbuffer = 0;
10724 rsurface.modeltvector3f_bufferoffset = 0;
10725 rsurface.modelnormal3f_vertexbuffer = 0;
10726 rsurface.modelnormal3f_bufferoffset = 0;
10727 rsurface.modelgeneratedvertex = true;
10731 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10732 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10733 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10734 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10735 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10736 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10737 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10738 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10739 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10740 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10741 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10742 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10743 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10744 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10745 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10746 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10747 rsurface.modelgeneratedvertex = false;
10749 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10750 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10751 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10752 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10753 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10754 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10755 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10756 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10757 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10758 rsurface.modelelement3i = model->surfmesh.data_element3i;
10759 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10760 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10761 rsurface.modelelement3s = model->surfmesh.data_element3s;
10762 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10763 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10764 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10765 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10766 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10767 rsurface.modelsurfaces = model->data_surfaces;
10768 rsurface.batchgeneratedvertex = false;
10769 rsurface.batchfirstvertex = 0;
10770 rsurface.batchnumvertices = 0;
10771 rsurface.batchfirsttriangle = 0;
10772 rsurface.batchnumtriangles = 0;
10773 rsurface.batchvertex3f = NULL;
10774 rsurface.batchvertex3f_vertexbuffer = NULL;
10775 rsurface.batchvertex3f_bufferoffset = 0;
10776 rsurface.batchsvector3f = NULL;
10777 rsurface.batchsvector3f_vertexbuffer = NULL;
10778 rsurface.batchsvector3f_bufferoffset = 0;
10779 rsurface.batchtvector3f = NULL;
10780 rsurface.batchtvector3f_vertexbuffer = NULL;
10781 rsurface.batchtvector3f_bufferoffset = 0;
10782 rsurface.batchnormal3f = NULL;
10783 rsurface.batchnormal3f_vertexbuffer = NULL;
10784 rsurface.batchnormal3f_bufferoffset = 0;
10785 rsurface.batchlightmapcolor4f = NULL;
10786 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10787 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10788 rsurface.batchtexcoordtexture2f = NULL;
10789 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10790 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10791 rsurface.batchtexcoordlightmap2f = NULL;
10792 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10793 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10794 rsurface.batchvertexmesh = NULL;
10795 rsurface.batchvertexmeshbuffer = NULL;
10796 rsurface.batchvertexposition = NULL;
10797 rsurface.batchvertexpositionbuffer = NULL;
10798 rsurface.batchelement3i = NULL;
10799 rsurface.batchelement3i_indexbuffer = NULL;
10800 rsurface.batchelement3i_bufferoffset = 0;
10801 rsurface.batchelement3s = NULL;
10802 rsurface.batchelement3s_indexbuffer = NULL;
10803 rsurface.batchelement3s_bufferoffset = 0;
10804 rsurface.passcolor4f = NULL;
10805 rsurface.passcolor4f_vertexbuffer = NULL;
10806 rsurface.passcolor4f_bufferoffset = 0;
10809 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)
10813 rsurface.entity = r_refdef.scene.worldentity;
10814 rsurface.skeleton = NULL;
10815 rsurface.ent_skinnum = 0;
10816 rsurface.ent_qwskin = -1;
10817 rsurface.ent_shadertime = shadertime;
10818 rsurface.ent_flags = entflags;
10819 rsurface.modelnumvertices = numvertices;
10820 rsurface.modelnumtriangles = numtriangles;
10821 if (rsurface.array_size < rsurface.modelnumvertices)
10822 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10823 rsurface.matrix = *matrix;
10824 rsurface.inversematrix = *inversematrix;
10825 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10826 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10827 R_EntityMatrix(&rsurface.matrix);
10828 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10829 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10830 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10831 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10832 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10833 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10834 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10835 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10836 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10837 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10838 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10839 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10840 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);
10841 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10842 rsurface.frameblend[0].lerp = 1;
10843 rsurface.ent_alttextures = false;
10844 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10845 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10848 rsurface.modelvertex3f = vertex3f;
10849 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10850 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10851 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10853 else if (wantnormals)
10855 rsurface.modelvertex3f = vertex3f;
10856 rsurface.modelsvector3f = NULL;
10857 rsurface.modeltvector3f = NULL;
10858 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10862 rsurface.modelvertex3f = vertex3f;
10863 rsurface.modelsvector3f = NULL;
10864 rsurface.modeltvector3f = NULL;
10865 rsurface.modelnormal3f = NULL;
10867 rsurface.modelvertexmesh = NULL;
10868 rsurface.modelvertexmeshbuffer = NULL;
10869 rsurface.modelvertexposition = NULL;
10870 rsurface.modelvertexpositionbuffer = NULL;
10871 rsurface.modelvertex3f_vertexbuffer = 0;
10872 rsurface.modelvertex3f_bufferoffset = 0;
10873 rsurface.modelsvector3f_vertexbuffer = 0;
10874 rsurface.modelsvector3f_bufferoffset = 0;
10875 rsurface.modeltvector3f_vertexbuffer = 0;
10876 rsurface.modeltvector3f_bufferoffset = 0;
10877 rsurface.modelnormal3f_vertexbuffer = 0;
10878 rsurface.modelnormal3f_bufferoffset = 0;
10879 rsurface.modelgeneratedvertex = true;
10880 rsurface.modellightmapcolor4f = color4f;
10881 rsurface.modellightmapcolor4f_vertexbuffer = 0;
10882 rsurface.modellightmapcolor4f_bufferoffset = 0;
10883 rsurface.modeltexcoordtexture2f = texcoord2f;
10884 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10885 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10886 rsurface.modeltexcoordlightmap2f = NULL;
10887 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10888 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10889 rsurface.modelelement3i = element3i;
10890 rsurface.modelelement3i_indexbuffer = NULL;
10891 rsurface.modelelement3i_bufferoffset = 0;
10892 rsurface.modelelement3s = element3s;
10893 rsurface.modelelement3s_indexbuffer = NULL;
10894 rsurface.modelelement3s_bufferoffset = 0;
10895 rsurface.modellightmapoffsets = NULL;
10896 rsurface.modelsurfaces = NULL;
10897 rsurface.batchgeneratedvertex = false;
10898 rsurface.batchfirstvertex = 0;
10899 rsurface.batchnumvertices = 0;
10900 rsurface.batchfirsttriangle = 0;
10901 rsurface.batchnumtriangles = 0;
10902 rsurface.batchvertex3f = NULL;
10903 rsurface.batchvertex3f_vertexbuffer = NULL;
10904 rsurface.batchvertex3f_bufferoffset = 0;
10905 rsurface.batchsvector3f = NULL;
10906 rsurface.batchsvector3f_vertexbuffer = NULL;
10907 rsurface.batchsvector3f_bufferoffset = 0;
10908 rsurface.batchtvector3f = NULL;
10909 rsurface.batchtvector3f_vertexbuffer = NULL;
10910 rsurface.batchtvector3f_bufferoffset = 0;
10911 rsurface.batchnormal3f = NULL;
10912 rsurface.batchnormal3f_vertexbuffer = NULL;
10913 rsurface.batchnormal3f_bufferoffset = 0;
10914 rsurface.batchlightmapcolor4f = NULL;
10915 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10916 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10917 rsurface.batchtexcoordtexture2f = NULL;
10918 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10919 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10920 rsurface.batchtexcoordlightmap2f = NULL;
10921 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10922 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10923 rsurface.batchvertexmesh = NULL;
10924 rsurface.batchvertexmeshbuffer = NULL;
10925 rsurface.batchvertexposition = NULL;
10926 rsurface.batchvertexpositionbuffer = NULL;
10927 rsurface.batchelement3i = NULL;
10928 rsurface.batchelement3i_indexbuffer = NULL;
10929 rsurface.batchelement3i_bufferoffset = 0;
10930 rsurface.batchelement3s = NULL;
10931 rsurface.batchelement3s_indexbuffer = NULL;
10932 rsurface.batchelement3s_bufferoffset = 0;
10933 rsurface.passcolor4f = NULL;
10934 rsurface.passcolor4f_vertexbuffer = NULL;
10935 rsurface.passcolor4f_bufferoffset = 0;
10937 if (rsurface.modelnumvertices && rsurface.modelelement3i)
10939 if ((wantnormals || wanttangents) && !normal3f)
10941 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10942 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10944 if (wanttangents && !svector3f)
10946 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);
10947 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10948 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10952 // now convert arrays into vertexmesh structs
10953 for (i = 0;i < numvertices;i++)
10955 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10956 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10957 if (rsurface.modelsvector3f)
10958 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10959 if (rsurface.modeltvector3f)
10960 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10961 if (rsurface.modelnormal3f)
10962 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10963 if (rsurface.modellightmapcolor4f)
10964 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10965 if (rsurface.modeltexcoordtexture2f)
10966 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10967 if (rsurface.modeltexcoordlightmap2f)
10968 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10972 float RSurf_FogPoint(const float *v)
10974 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10975 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10976 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10977 float FogHeightFade = r_refdef.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(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10985 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10988 float RSurf_FogVertex(const float *v)
10990 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10991 float FogPlaneViewDist = rsurface.fogplaneviewdist;
10992 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10993 float FogHeightFade = rsurface.fogheightfade;
10995 unsigned int fogmasktableindex;
10996 if (r_refdef.fogplaneviewabove)
10997 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10999 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11000 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11001 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11004 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11007 for (i = 0;i < numelements;i++)
11008 outelement3i[i] = inelement3i[i] + adjust;
11011 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11012 extern cvar_t gl_vbo;
11013 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11021 int surfacefirsttriangle;
11022 int surfacenumtriangles;
11023 int surfacefirstvertex;
11024 int surfaceendvertex;
11025 int surfacenumvertices;
11026 int surfaceadjustvertex;
11030 qboolean dynamicvertex;
11034 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11035 float waveparms[4];
11036 q3shaderinfo_deform_t *deform;
11037 const msurface_t *surface, *firstsurface;
11038 r_vertexposition_t *vertexposition;
11039 r_vertexmesh_t *vertexmesh;
11040 if (!texturenumsurfaces)
11042 // find vertex range of this surface batch
11044 firstsurface = texturesurfacelist[0];
11045 firsttriangle = firstsurface->num_firsttriangle;
11047 firstvertex = endvertex = firstsurface->num_firstvertex;
11048 for (i = 0;i < texturenumsurfaces;i++)
11050 surface = texturesurfacelist[i];
11051 if (surface != firstsurface + i)
11053 surfacefirstvertex = surface->num_firstvertex;
11054 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11055 surfacenumtriangles = surface->num_triangles;
11056 if (firstvertex > surfacefirstvertex)
11057 firstvertex = surfacefirstvertex;
11058 if (endvertex < surfaceendvertex)
11059 endvertex = surfaceendvertex;
11060 numtriangles += surfacenumtriangles;
11065 // we now know the vertex range used, and if there are any gaps in it
11066 rsurface.batchfirstvertex = firstvertex;
11067 rsurface.batchnumvertices = endvertex - firstvertex;
11068 rsurface.batchfirsttriangle = firsttriangle;
11069 rsurface.batchnumtriangles = numtriangles;
11071 // this variable holds flags for which properties have been updated that
11072 // may require regenerating vertexmesh or vertexposition arrays...
11075 // check if any dynamic vertex processing must occur
11076 dynamicvertex = false;
11078 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11079 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11080 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11082 switch (deform->deform)
11085 case Q3DEFORM_PROJECTIONSHADOW:
11086 case Q3DEFORM_TEXT0:
11087 case Q3DEFORM_TEXT1:
11088 case Q3DEFORM_TEXT2:
11089 case Q3DEFORM_TEXT3:
11090 case Q3DEFORM_TEXT4:
11091 case Q3DEFORM_TEXT5:
11092 case Q3DEFORM_TEXT6:
11093 case Q3DEFORM_TEXT7:
11094 case Q3DEFORM_NONE:
11096 case Q3DEFORM_AUTOSPRITE:
11097 dynamicvertex = true;
11098 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11099 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11101 case Q3DEFORM_AUTOSPRITE2:
11102 dynamicvertex = true;
11103 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11104 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11106 case Q3DEFORM_NORMAL:
11107 dynamicvertex = true;
11108 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11109 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11111 case Q3DEFORM_WAVE:
11112 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11113 break; // if wavefunc is a nop, ignore this transform
11114 dynamicvertex = true;
11115 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11116 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11118 case Q3DEFORM_BULGE:
11119 dynamicvertex = true;
11120 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11121 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11123 case Q3DEFORM_MOVE:
11124 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11125 break; // if wavefunc is a nop, ignore this transform
11126 dynamicvertex = true;
11127 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11128 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11132 switch(rsurface.texture->tcgen.tcgen)
11135 case Q3TCGEN_TEXTURE:
11137 case Q3TCGEN_LIGHTMAP:
11138 dynamicvertex = true;
11139 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11140 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11142 case Q3TCGEN_VECTOR:
11143 dynamicvertex = true;
11144 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11145 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11147 case Q3TCGEN_ENVIRONMENT:
11148 dynamicvertex = true;
11149 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11150 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11153 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11155 dynamicvertex = true;
11156 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11157 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11160 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11162 dynamicvertex = true;
11163 batchneed |= BATCHNEED_NOGAPS;
11164 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11167 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11169 dynamicvertex = true;
11170 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11171 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11174 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11176 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11177 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11178 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11179 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11180 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11181 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11182 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11185 // when the model data has no vertex buffer (dynamic mesh), we need to
11187 if (!rsurface.modelvertexmeshbuffer)
11188 batchneed |= BATCHNEED_NOGAPS;
11190 // if needsupdate, we have to do a dynamic vertex batch for sure
11191 if (needsupdate & batchneed)
11192 dynamicvertex = true;
11194 // see if we need to build vertexmesh from arrays
11195 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11196 dynamicvertex = true;
11198 // see if we need to build vertexposition from arrays
11199 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11200 dynamicvertex = true;
11202 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11203 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11204 dynamicvertex = true;
11206 // if there is a chance of animated vertex colors, it's a dynamic batch
11207 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11208 dynamicvertex = true;
11210 rsurface.batchvertex3f = rsurface.modelvertex3f;
11211 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11212 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11213 rsurface.batchsvector3f = rsurface.modelsvector3f;
11214 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11215 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11216 rsurface.batchtvector3f = rsurface.modeltvector3f;
11217 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11218 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11219 rsurface.batchnormal3f = rsurface.modelnormal3f;
11220 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11221 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11222 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11223 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11224 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11225 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11226 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11227 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11228 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11229 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11230 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11231 rsurface.batchvertexposition = rsurface.modelvertexposition;
11232 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11233 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11234 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11235 rsurface.batchelement3i = rsurface.modelelement3i;
11236 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11237 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11238 rsurface.batchelement3s = rsurface.modelelement3s;
11239 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11240 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11242 // if any dynamic vertex processing has to occur in software, we copy the
11243 // entire surface list together before processing to rebase the vertices
11244 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11246 // if any gaps exist and we do not have a static vertex buffer, we have to
11247 // copy the surface list together to avoid wasting upload bandwidth on the
11248 // vertices in the gaps.
11250 // if gaps exist and we have a static vertex buffer, we still have to
11251 // combine the index buffer ranges into one dynamic index buffer.
11253 // in all cases we end up with data that can be drawn in one call.
11255 if (!dynamicvertex)
11257 // static vertex data, just set pointers...
11258 rsurface.batchgeneratedvertex = false;
11259 // if there are gaps, we want to build a combined index buffer,
11260 // otherwise use the original static buffer with an appropriate offset
11265 for (i = 0;i < texturenumsurfaces;i++)
11267 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11268 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11269 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11270 numtriangles += surfacenumtriangles;
11272 rsurface.batchelement3i = rsurface.array_batchelement3i;
11273 rsurface.batchelement3i_indexbuffer = NULL;
11274 rsurface.batchelement3i_bufferoffset = 0;
11275 rsurface.batchelement3s = NULL;
11276 rsurface.batchelement3s_indexbuffer = NULL;
11277 rsurface.batchelement3s_bufferoffset = 0;
11278 if (endvertex <= 65536)
11280 rsurface.batchelement3s = rsurface.array_batchelement3s;
11281 for (i = 0;i < numtriangles*3;i++)
11282 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11284 rsurface.batchfirsttriangle = firsttriangle;
11285 rsurface.batchnumtriangles = numtriangles;
11290 // something needs software processing, do it for real...
11291 // we only directly handle interleaved array data in this case...
11292 rsurface.batchgeneratedvertex = true;
11294 // now copy the vertex data into a combined array and make an index array
11295 // (this is what Quake3 does all the time)
11296 //if (gaps || rsurface.batchfirstvertex)
11298 rsurface.batchvertexposition = NULL;
11299 rsurface.batchvertexpositionbuffer = NULL;
11300 rsurface.batchvertexmesh = NULL;
11301 rsurface.batchvertexmeshbuffer = NULL;
11302 rsurface.batchvertex3f = NULL;
11303 rsurface.batchvertex3f_vertexbuffer = NULL;
11304 rsurface.batchvertex3f_bufferoffset = 0;
11305 rsurface.batchsvector3f = NULL;
11306 rsurface.batchsvector3f_vertexbuffer = NULL;
11307 rsurface.batchsvector3f_bufferoffset = 0;
11308 rsurface.batchtvector3f = NULL;
11309 rsurface.batchtvector3f_vertexbuffer = NULL;
11310 rsurface.batchtvector3f_bufferoffset = 0;
11311 rsurface.batchnormal3f = NULL;
11312 rsurface.batchnormal3f_vertexbuffer = NULL;
11313 rsurface.batchnormal3f_bufferoffset = 0;
11314 rsurface.batchlightmapcolor4f = NULL;
11315 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11316 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11317 rsurface.batchtexcoordtexture2f = NULL;
11318 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11319 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11320 rsurface.batchtexcoordlightmap2f = NULL;
11321 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11322 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11323 rsurface.batchelement3i = rsurface.array_batchelement3i;
11324 rsurface.batchelement3i_indexbuffer = NULL;
11325 rsurface.batchelement3i_bufferoffset = 0;
11326 rsurface.batchelement3s = NULL;
11327 rsurface.batchelement3s_indexbuffer = NULL;
11328 rsurface.batchelement3s_bufferoffset = 0;
11329 // we'll only be setting up certain arrays as needed
11330 if (batchneed & BATCHNEED_VERTEXPOSITION)
11331 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11332 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11333 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11334 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11335 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11336 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11337 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11338 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11340 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11341 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11343 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11344 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11345 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11346 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11347 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11348 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11351 for (i = 0;i < texturenumsurfaces;i++)
11353 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11354 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11355 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11356 surfaceadjustvertex = numvertices - surfacefirstvertex;
11357 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11358 // copy only the data requested
11359 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11360 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11361 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11362 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11363 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11365 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11366 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11367 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11368 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11369 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11371 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11372 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11374 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11375 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11376 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11377 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11378 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11379 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11381 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11382 numvertices += surfacenumvertices;
11383 numtriangles += surfacenumtriangles;
11386 // generate a 16bit index array as well if possible
11387 // (in general, dynamic batches fit)
11388 if (numvertices <= 65536)
11390 rsurface.batchelement3s = rsurface.array_batchelement3s;
11391 for (i = 0;i < numtriangles*3;i++)
11392 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11395 // since we've copied everything, the batch now starts at 0
11396 rsurface.batchfirstvertex = 0;
11397 rsurface.batchnumvertices = numvertices;
11398 rsurface.batchfirsttriangle = 0;
11399 rsurface.batchnumtriangles = numtriangles;
11402 // q1bsp surfaces rendered in vertex color mode have to have colors
11403 // calculated based on lightstyles
11404 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11406 // generate color arrays for the surfaces in this list
11410 const int *offsets;
11411 const unsigned char *lm;
11413 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11414 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11415 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11416 for (i = 0;i < texturenumsurfaces;i++)
11418 surface = texturesurfacelist[i];
11419 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11420 surfacenumvertices = surface->num_vertices;
11421 if (surface->lightmapinfo->samples)
11423 for (j = 0;j < surfacenumvertices;j++)
11425 lm = surface->lightmapinfo->samples + offsets[j];
11426 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11427 VectorScale(lm, scale, c);
11428 if (surface->lightmapinfo->styles[1] != 255)
11430 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11432 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11433 VectorMA(c, scale, lm, c);
11434 if (surface->lightmapinfo->styles[2] != 255)
11437 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11438 VectorMA(c, scale, lm, c);
11439 if (surface->lightmapinfo->styles[3] != 255)
11442 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11443 VectorMA(c, scale, lm, c);
11450 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);
11456 for (j = 0;j < surfacenumvertices;j++)
11458 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11465 // if vertices are deformed (sprite flares and things in maps, possibly
11466 // water waves, bulges and other deformations), modify the copied vertices
11468 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11470 switch (deform->deform)
11473 case Q3DEFORM_PROJECTIONSHADOW:
11474 case Q3DEFORM_TEXT0:
11475 case Q3DEFORM_TEXT1:
11476 case Q3DEFORM_TEXT2:
11477 case Q3DEFORM_TEXT3:
11478 case Q3DEFORM_TEXT4:
11479 case Q3DEFORM_TEXT5:
11480 case Q3DEFORM_TEXT6:
11481 case Q3DEFORM_TEXT7:
11482 case Q3DEFORM_NONE:
11484 case Q3DEFORM_AUTOSPRITE:
11485 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11486 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11487 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11488 VectorNormalize(newforward);
11489 VectorNormalize(newright);
11490 VectorNormalize(newup);
11491 // a single autosprite surface can contain multiple sprites...
11492 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11494 VectorClear(center);
11495 for (i = 0;i < 4;i++)
11496 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11497 VectorScale(center, 0.25f, center);
11498 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11499 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11500 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11501 for (i = 0;i < 4;i++)
11503 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11504 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11507 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11508 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11509 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);
11510 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11511 rsurface.batchvertex3f_vertexbuffer = NULL;
11512 rsurface.batchvertex3f_bufferoffset = 0;
11513 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11514 rsurface.batchsvector3f_vertexbuffer = NULL;
11515 rsurface.batchsvector3f_bufferoffset = 0;
11516 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11517 rsurface.batchtvector3f_vertexbuffer = NULL;
11518 rsurface.batchtvector3f_bufferoffset = 0;
11519 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11520 rsurface.batchnormal3f_vertexbuffer = NULL;
11521 rsurface.batchnormal3f_bufferoffset = 0;
11523 case Q3DEFORM_AUTOSPRITE2:
11524 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11525 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11526 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11527 VectorNormalize(newforward);
11528 VectorNormalize(newright);
11529 VectorNormalize(newup);
11531 const float *v1, *v2;
11541 memset(shortest, 0, sizeof(shortest));
11542 // a single autosprite surface can contain multiple sprites...
11543 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11545 VectorClear(center);
11546 for (i = 0;i < 4;i++)
11547 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11548 VectorScale(center, 0.25f, center);
11549 // find the two shortest edges, then use them to define the
11550 // axis vectors for rotating around the central axis
11551 for (i = 0;i < 6;i++)
11553 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11554 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11555 l = VectorDistance2(v1, v2);
11556 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11557 if (v1[2] != v2[2])
11558 l += (1.0f / 1024.0f);
11559 if (shortest[0].length2 > l || i == 0)
11561 shortest[1] = shortest[0];
11562 shortest[0].length2 = l;
11563 shortest[0].v1 = v1;
11564 shortest[0].v2 = v2;
11566 else if (shortest[1].length2 > l || i == 1)
11568 shortest[1].length2 = l;
11569 shortest[1].v1 = v1;
11570 shortest[1].v2 = v2;
11573 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11574 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11575 // this calculates the right vector from the shortest edge
11576 // and the up vector from the edge midpoints
11577 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11578 VectorNormalize(right);
11579 VectorSubtract(end, start, up);
11580 VectorNormalize(up);
11581 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11582 VectorSubtract(rsurface.localvieworigin, center, forward);
11583 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11584 VectorNegate(forward, forward);
11585 VectorReflect(forward, 0, up, forward);
11586 VectorNormalize(forward);
11587 CrossProduct(up, forward, newright);
11588 VectorNormalize(newright);
11589 // rotate the quad around the up axis vector, this is made
11590 // especially easy by the fact we know the quad is flat,
11591 // so we only have to subtract the center position and
11592 // measure distance along the right vector, and then
11593 // multiply that by the newright vector and add back the
11595 // we also need to subtract the old position to undo the
11596 // displacement from the center, which we do with a
11597 // DotProduct, the subtraction/addition of center is also
11598 // optimized into DotProducts here
11599 l = DotProduct(right, center);
11600 for (i = 0;i < 4;i++)
11602 v1 = rsurface.batchvertex3f + 3*(j+i);
11603 f = DotProduct(right, v1) - l;
11604 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11608 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11609 rsurface.batchvertex3f_vertexbuffer = NULL;
11610 rsurface.batchvertex3f_bufferoffset = 0;
11611 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11613 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11614 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11615 rsurface.batchnormal3f_vertexbuffer = NULL;
11616 rsurface.batchnormal3f_bufferoffset = 0;
11618 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11620 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);
11621 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11622 rsurface.batchsvector3f_vertexbuffer = NULL;
11623 rsurface.batchsvector3f_bufferoffset = 0;
11624 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11625 rsurface.batchtvector3f_vertexbuffer = NULL;
11626 rsurface.batchtvector3f_bufferoffset = 0;
11629 case Q3DEFORM_NORMAL:
11630 // deform the normals to make reflections wavey
11631 for (j = 0;j < rsurface.batchnumvertices;j++)
11634 float *normal = rsurface.array_batchnormal3f + 3*j;
11635 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11636 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11637 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]);
11638 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]);
11639 VectorNormalize(normal);
11641 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11642 rsurface.batchnormal3f_vertexbuffer = NULL;
11643 rsurface.batchnormal3f_bufferoffset = 0;
11644 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11646 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);
11647 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11648 rsurface.batchsvector3f_vertexbuffer = NULL;
11649 rsurface.batchsvector3f_bufferoffset = 0;
11650 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11651 rsurface.batchtvector3f_vertexbuffer = NULL;
11652 rsurface.batchtvector3f_bufferoffset = 0;
11655 case Q3DEFORM_WAVE:
11656 // deform vertex array to make wavey water and flags and such
11657 waveparms[0] = deform->waveparms[0];
11658 waveparms[1] = deform->waveparms[1];
11659 waveparms[2] = deform->waveparms[2];
11660 waveparms[3] = deform->waveparms[3];
11661 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11662 break; // if wavefunc is a nop, don't make a dynamic vertex array
11663 // this is how a divisor of vertex influence on deformation
11664 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11665 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11666 for (j = 0;j < rsurface.batchnumvertices;j++)
11668 // if the wavefunc depends on time, evaluate it per-vertex
11671 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11672 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11674 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11676 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11677 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11678 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11679 rsurface.batchvertex3f_vertexbuffer = NULL;
11680 rsurface.batchvertex3f_bufferoffset = 0;
11681 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11682 rsurface.batchnormal3f_vertexbuffer = NULL;
11683 rsurface.batchnormal3f_bufferoffset = 0;
11684 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11686 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);
11687 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11688 rsurface.batchsvector3f_vertexbuffer = NULL;
11689 rsurface.batchsvector3f_bufferoffset = 0;
11690 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11691 rsurface.batchtvector3f_vertexbuffer = NULL;
11692 rsurface.batchtvector3f_bufferoffset = 0;
11695 case Q3DEFORM_BULGE:
11696 // deform vertex array to make the surface have moving bulges
11697 for (j = 0;j < rsurface.batchnumvertices;j++)
11699 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11700 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11702 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11703 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11704 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11705 rsurface.batchvertex3f_vertexbuffer = NULL;
11706 rsurface.batchvertex3f_bufferoffset = 0;
11707 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11708 rsurface.batchnormal3f_vertexbuffer = NULL;
11709 rsurface.batchnormal3f_bufferoffset = 0;
11710 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11712 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);
11713 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11714 rsurface.batchsvector3f_vertexbuffer = NULL;
11715 rsurface.batchsvector3f_bufferoffset = 0;
11716 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11717 rsurface.batchtvector3f_vertexbuffer = NULL;
11718 rsurface.batchtvector3f_bufferoffset = 0;
11721 case Q3DEFORM_MOVE:
11722 // deform vertex array
11723 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11724 break; // if wavefunc is a nop, don't make a dynamic vertex array
11725 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11726 VectorScale(deform->parms, scale, waveparms);
11727 for (j = 0;j < rsurface.batchnumvertices;j++)
11728 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11729 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11730 rsurface.batchvertex3f_vertexbuffer = NULL;
11731 rsurface.batchvertex3f_bufferoffset = 0;
11736 // generate texcoords based on the chosen texcoord source
11737 switch(rsurface.texture->tcgen.tcgen)
11740 case Q3TCGEN_TEXTURE:
11742 case Q3TCGEN_LIGHTMAP:
11743 if (rsurface.batchtexcoordlightmap2f)
11744 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11745 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11746 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11747 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11749 case Q3TCGEN_VECTOR:
11750 for (j = 0;j < rsurface.batchnumvertices;j++)
11752 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11753 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11755 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11756 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11757 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11759 case Q3TCGEN_ENVIRONMENT:
11760 // make environment reflections using a spheremap
11761 for (j = 0;j < rsurface.batchnumvertices;j++)
11763 // identical to Q3A's method, but executed in worldspace so
11764 // carried models can be shiny too
11766 float viewer[3], d, reflected[3], worldreflected[3];
11768 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11769 // VectorNormalize(viewer);
11771 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11773 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11774 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11775 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11776 // note: this is proportinal to viewer, so we can normalize later
11778 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11779 VectorNormalize(worldreflected);
11781 // note: this sphere map only uses world x and z!
11782 // so positive and negative y will LOOK THE SAME.
11783 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11784 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11786 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11787 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11788 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11791 // the only tcmod that needs software vertex processing is turbulent, so
11792 // check for it here and apply the changes if needed
11793 // and we only support that as the first one
11794 // (handling a mixture of turbulent and other tcmods would be problematic
11795 // without punting it entirely to a software path)
11796 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11798 amplitude = rsurface.texture->tcmods[0].parms[1];
11799 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11800 for (j = 0;j < rsurface.batchnumvertices;j++)
11802 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);
11803 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11805 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11806 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11807 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11810 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11812 // convert the modified arrays to vertex structs
11813 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11814 rsurface.batchvertexmeshbuffer = NULL;
11815 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11816 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11817 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11818 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11819 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11820 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11821 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11823 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11825 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11826 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11829 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11830 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11831 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11832 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11833 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11834 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11835 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11836 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11837 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11840 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11842 // convert the modified arrays to vertex structs
11843 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11844 rsurface.batchvertexpositionbuffer = NULL;
11845 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11846 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11848 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11849 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11853 void RSurf_DrawBatch(void)
11855 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);
11858 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11860 // pick the closest matching water plane
11861 int planeindex, vertexindex, bestplaneindex = -1;
11865 r_waterstate_waterplane_t *p;
11867 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11869 if(p->camera_entity != rsurface.texture->camera_entity)
11872 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11873 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11875 Matrix4x4_Transform(&rsurface.matrix, v, vert);
11876 d += fabs(PlaneDiff(vert, &p->plane));
11878 if (bestd > d || bestplaneindex < 0)
11881 bestplaneindex = planeindex;
11884 return bestplaneindex;
11887 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11890 for (i = 0;i < rsurface.batchnumvertices;i++)
11891 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11892 rsurface.passcolor4f = rsurface.array_passcolor4f;
11893 rsurface.passcolor4f_vertexbuffer = 0;
11894 rsurface.passcolor4f_bufferoffset = 0;
11897 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11904 if (rsurface.passcolor4f)
11906 // generate color arrays
11907 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)
11909 f = RSurf_FogVertex(v);
11918 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11920 f = RSurf_FogVertex(v);
11927 rsurface.passcolor4f = rsurface.array_passcolor4f;
11928 rsurface.passcolor4f_vertexbuffer = 0;
11929 rsurface.passcolor4f_bufferoffset = 0;
11932 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11939 if (!rsurface.passcolor4f)
11941 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)
11943 f = RSurf_FogVertex(v);
11944 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11945 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11946 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11949 rsurface.passcolor4f = rsurface.array_passcolor4f;
11950 rsurface.passcolor4f_vertexbuffer = 0;
11951 rsurface.passcolor4f_bufferoffset = 0;
11954 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11959 if (!rsurface.passcolor4f)
11961 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11968 rsurface.passcolor4f = rsurface.array_passcolor4f;
11969 rsurface.passcolor4f_vertexbuffer = 0;
11970 rsurface.passcolor4f_bufferoffset = 0;
11973 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11978 if (!rsurface.passcolor4f)
11980 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11982 c2[0] = c[0] + r_refdef.scene.ambient;
11983 c2[1] = c[1] + r_refdef.scene.ambient;
11984 c2[2] = c[2] + r_refdef.scene.ambient;
11987 rsurface.passcolor4f = rsurface.array_passcolor4f;
11988 rsurface.passcolor4f_vertexbuffer = 0;
11989 rsurface.passcolor4f_bufferoffset = 0;
11992 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11995 rsurface.passcolor4f = NULL;
11996 rsurface.passcolor4f_vertexbuffer = 0;
11997 rsurface.passcolor4f_bufferoffset = 0;
11998 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
11999 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12000 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12001 GL_Color(r, g, b, a);
12002 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12006 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12008 // TODO: optimize applyfog && applycolor case
12009 // just apply fog if necessary, and tint the fog color array if necessary
12010 rsurface.passcolor4f = NULL;
12011 rsurface.passcolor4f_vertexbuffer = 0;
12012 rsurface.passcolor4f_bufferoffset = 0;
12013 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12014 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12015 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12016 GL_Color(r, g, b, a);
12020 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12023 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12024 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12025 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12026 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12027 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12028 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12029 GL_Color(r, g, b, a);
12033 static void RSurf_DrawBatch_GL11_ClampColor(void)
12038 if (!rsurface.passcolor4f)
12040 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12042 c2[0] = bound(0.0f, c1[0], 1.0f);
12043 c2[1] = bound(0.0f, c1[1], 1.0f);
12044 c2[2] = bound(0.0f, c1[2], 1.0f);
12045 c2[3] = bound(0.0f, c1[3], 1.0f);
12049 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12057 vec3_t ambientcolor;
12058 vec3_t diffusecolor;
12062 VectorCopy(rsurface.modellight_lightdir, lightdir);
12063 f = 0.5f * r_refdef.lightmapintensity;
12064 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12065 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12066 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12067 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12068 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12069 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12071 if (VectorLength2(diffusecolor) > 0)
12073 // q3-style directional shading
12074 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)
12076 if ((f = DotProduct(n, lightdir)) > 0)
12077 VectorMA(ambientcolor, f, diffusecolor, c);
12079 VectorCopy(ambientcolor, c);
12086 rsurface.passcolor4f = rsurface.array_passcolor4f;
12087 rsurface.passcolor4f_vertexbuffer = 0;
12088 rsurface.passcolor4f_bufferoffset = 0;
12089 *applycolor = false;
12093 *r = ambientcolor[0];
12094 *g = ambientcolor[1];
12095 *b = ambientcolor[2];
12096 rsurface.passcolor4f = NULL;
12097 rsurface.passcolor4f_vertexbuffer = 0;
12098 rsurface.passcolor4f_bufferoffset = 0;
12102 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12104 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12105 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12106 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12107 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12108 GL_Color(r, g, b, a);
12112 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12118 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12120 f = 1 - RSurf_FogVertex(v);
12128 void RSurf_SetupDepthAndCulling(void)
12130 // submodels are biased to avoid z-fighting with world surfaces that they
12131 // may be exactly overlapping (avoids z-fighting artifacts on certain
12132 // doors and things in Quake maps)
12133 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12134 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12135 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12136 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12139 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12141 // transparent sky would be ridiculous
12142 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12144 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12145 skyrenderlater = true;
12146 RSurf_SetupDepthAndCulling();
12147 GL_DepthMask(true);
12148 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12149 // skymasking on them, and Quake3 never did sky masking (unlike
12150 // software Quake and software Quake2), so disable the sky masking
12151 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12152 // and skymasking also looks very bad when noclipping outside the
12153 // level, so don't use it then either.
12154 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12156 R_Mesh_ResetTextureState();
12157 if (skyrendermasked)
12159 R_SetupShader_DepthOrShadow();
12160 // depth-only (masking)
12161 GL_ColorMask(0,0,0,0);
12162 // just to make sure that braindead drivers don't draw
12163 // anything despite that colormask...
12164 GL_BlendFunc(GL_ZERO, GL_ONE);
12165 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12166 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12170 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12172 GL_BlendFunc(GL_ONE, GL_ZERO);
12173 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12174 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12175 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12178 if (skyrendermasked)
12179 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12181 R_Mesh_ResetTextureState();
12182 GL_Color(1, 1, 1, 1);
12185 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12186 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12187 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12189 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12193 // render screenspace normalmap to texture
12194 GL_DepthMask(true);
12195 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12200 // bind lightmap texture
12202 // water/refraction/reflection/camera surfaces have to be handled specially
12203 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12205 int start, end, startplaneindex;
12206 for (start = 0;start < texturenumsurfaces;start = end)
12208 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12209 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12211 // now that we have a batch using the same planeindex, render it
12212 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12214 // render water or distortion background
12215 GL_DepthMask(true);
12216 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));
12218 // blend surface on top
12219 GL_DepthMask(false);
12220 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12223 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12225 // render surface with reflection texture as input
12226 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12227 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));
12234 // render surface batch normally
12235 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12236 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12240 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12242 // OpenGL 1.3 path - anything not completely ancient
12243 qboolean applycolor;
12246 const texturelayer_t *layer;
12247 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);
12248 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12250 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12253 int layertexrgbscale;
12254 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12256 if (layerindex == 0)
12257 GL_AlphaTest(true);
12260 GL_AlphaTest(false);
12261 GL_DepthFunc(GL_EQUAL);
12264 GL_DepthMask(layer->depthmask && writedepth);
12265 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12266 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12268 layertexrgbscale = 4;
12269 VectorScale(layer->color, 0.25f, layercolor);
12271 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12273 layertexrgbscale = 2;
12274 VectorScale(layer->color, 0.5f, layercolor);
12278 layertexrgbscale = 1;
12279 VectorScale(layer->color, 1.0f, layercolor);
12281 layercolor[3] = layer->color[3];
12282 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12283 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12284 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12285 switch (layer->type)
12287 case TEXTURELAYERTYPE_LITTEXTURE:
12288 // single-pass lightmapped texture with 2x rgbscale
12289 R_Mesh_TexBind(0, r_texture_white);
12290 R_Mesh_TexMatrix(0, NULL);
12291 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12292 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12293 R_Mesh_TexBind(1, layer->texture);
12294 R_Mesh_TexMatrix(1, &layer->texmatrix);
12295 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12296 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12297 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12298 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12299 else if (rsurface.uselightmaptexture)
12300 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12302 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12304 case TEXTURELAYERTYPE_TEXTURE:
12305 // singletexture unlit texture with transparency support
12306 R_Mesh_TexBind(0, layer->texture);
12307 R_Mesh_TexMatrix(0, &layer->texmatrix);
12308 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12309 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12310 R_Mesh_TexBind(1, 0);
12311 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12312 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12314 case TEXTURELAYERTYPE_FOG:
12315 // singletexture fogging
12316 if (layer->texture)
12318 R_Mesh_TexBind(0, layer->texture);
12319 R_Mesh_TexMatrix(0, &layer->texmatrix);
12320 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12321 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12325 R_Mesh_TexBind(0, 0);
12326 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12328 R_Mesh_TexBind(1, 0);
12329 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12330 // generate a color array for the fog pass
12331 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12332 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12336 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12341 GL_DepthFunc(GL_LEQUAL);
12342 GL_AlphaTest(false);
12346 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12348 // OpenGL 1.1 - crusty old voodoo path
12351 const texturelayer_t *layer;
12352 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);
12353 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12355 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12357 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12359 if (layerindex == 0)
12360 GL_AlphaTest(true);
12363 GL_AlphaTest(false);
12364 GL_DepthFunc(GL_EQUAL);
12367 GL_DepthMask(layer->depthmask && writedepth);
12368 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12369 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12370 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12371 switch (layer->type)
12373 case TEXTURELAYERTYPE_LITTEXTURE:
12374 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12376 // two-pass lit texture with 2x rgbscale
12377 // first the lightmap pass
12378 R_Mesh_TexBind(0, r_texture_white);
12379 R_Mesh_TexMatrix(0, NULL);
12380 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12381 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12382 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12383 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12384 else if (rsurface.uselightmaptexture)
12385 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12387 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12388 // then apply the texture to it
12389 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12390 R_Mesh_TexBind(0, layer->texture);
12391 R_Mesh_TexMatrix(0, &layer->texmatrix);
12392 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12393 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12394 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);
12398 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12399 R_Mesh_TexBind(0, layer->texture);
12400 R_Mesh_TexMatrix(0, &layer->texmatrix);
12401 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12402 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12403 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12404 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);
12406 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);
12409 case TEXTURELAYERTYPE_TEXTURE:
12410 // singletexture unlit texture with transparency support
12411 R_Mesh_TexBind(0, layer->texture);
12412 R_Mesh_TexMatrix(0, &layer->texmatrix);
12413 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12414 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12415 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);
12417 case TEXTURELAYERTYPE_FOG:
12418 // singletexture fogging
12419 if (layer->texture)
12421 R_Mesh_TexBind(0, layer->texture);
12422 R_Mesh_TexMatrix(0, &layer->texmatrix);
12423 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12424 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12428 R_Mesh_TexBind(0, 0);
12429 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12431 // generate a color array for the fog pass
12432 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12433 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12437 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12440 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12442 GL_DepthFunc(GL_LEQUAL);
12443 GL_AlphaTest(false);
12447 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12451 r_vertexgeneric_t *batchvertex;
12454 GL_AlphaTest(false);
12455 R_Mesh_ResetTextureState();
12456 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12458 if(rsurface.texture && rsurface.texture->currentskinframe)
12460 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12461 c[3] *= rsurface.texture->currentalpha;
12471 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12473 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12474 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12475 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12478 // brighten it up (as texture value 127 means "unlit")
12479 c[0] *= 2 * r_refdef.view.colorscale;
12480 c[1] *= 2 * r_refdef.view.colorscale;
12481 c[2] *= 2 * r_refdef.view.colorscale;
12483 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12484 c[3] *= r_wateralpha.value;
12486 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12488 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12489 GL_DepthMask(false);
12491 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12493 GL_BlendFunc(GL_ONE, GL_ONE);
12494 GL_DepthMask(false);
12496 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12498 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12499 GL_DepthMask(false);
12501 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12503 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12504 GL_DepthMask(false);
12508 GL_BlendFunc(GL_ONE, GL_ZERO);
12509 GL_DepthMask(writedepth);
12512 if (r_showsurfaces.integer == 3)
12514 rsurface.passcolor4f = NULL;
12516 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12518 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12520 rsurface.passcolor4f = NULL;
12521 rsurface.passcolor4f_vertexbuffer = 0;
12522 rsurface.passcolor4f_bufferoffset = 0;
12524 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12526 qboolean applycolor = true;
12529 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12531 r_refdef.lightmapintensity = 1;
12532 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12533 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12537 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12539 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12540 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12541 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12544 if(!rsurface.passcolor4f)
12545 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12547 RSurf_DrawBatch_GL11_ApplyAmbient();
12548 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12549 if(r_refdef.fogenabled)
12550 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12551 RSurf_DrawBatch_GL11_ClampColor();
12553 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12554 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12557 else if (!r_refdef.view.showdebug)
12559 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12560 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12561 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12563 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12564 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12566 R_Mesh_PrepareVertices_Generic_Unlock();
12569 else if (r_showsurfaces.integer == 4)
12571 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12572 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12573 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12575 unsigned char c = vi << 3;
12576 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12577 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12579 R_Mesh_PrepareVertices_Generic_Unlock();
12582 else if (r_showsurfaces.integer == 2)
12585 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12586 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12587 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12589 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12590 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12591 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12592 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12593 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12594 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12595 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12597 R_Mesh_PrepareVertices_Generic_Unlock();
12598 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12602 int texturesurfaceindex;
12604 const msurface_t *surface;
12605 unsigned char surfacecolor4ub[4];
12606 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12607 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12609 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12611 surface = texturesurfacelist[texturesurfaceindex];
12612 k = (int)(((size_t)surface) / sizeof(msurface_t));
12613 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12614 for (j = 0;j < surface->num_vertices;j++)
12616 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12617 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12621 R_Mesh_PrepareVertices_Generic_Unlock();
12626 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12629 RSurf_SetupDepthAndCulling();
12630 if (r_showsurfaces.integer)
12632 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12635 switch (vid.renderpath)
12637 case RENDERPATH_GL20:
12638 case RENDERPATH_CGGL:
12639 case RENDERPATH_D3D9:
12640 case RENDERPATH_D3D10:
12641 case RENDERPATH_D3D11:
12642 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12644 case RENDERPATH_GL13:
12645 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12647 case RENDERPATH_GL11:
12648 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12654 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12657 RSurf_SetupDepthAndCulling();
12658 if (r_showsurfaces.integer)
12660 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12663 switch (vid.renderpath)
12665 case RENDERPATH_GL20:
12666 case RENDERPATH_CGGL:
12667 case RENDERPATH_D3D9:
12668 case RENDERPATH_D3D10:
12669 case RENDERPATH_D3D11:
12670 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12672 case RENDERPATH_GL13:
12673 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12675 case RENDERPATH_GL11:
12676 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12682 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12685 int texturenumsurfaces, endsurface;
12686 texture_t *texture;
12687 const msurface_t *surface;
12688 #define MAXBATCH_TRANSPARENTSURFACES 256
12689 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12691 // if the model is static it doesn't matter what value we give for
12692 // wantnormals and wanttangents, so this logic uses only rules applicable
12693 // to a model, knowing that they are meaningless otherwise
12694 if (ent == r_refdef.scene.worldentity)
12695 RSurf_ActiveWorldEntity();
12696 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12697 RSurf_ActiveModelEntity(ent, false, false, false);
12700 switch (vid.renderpath)
12702 case RENDERPATH_GL20:
12703 case RENDERPATH_CGGL:
12704 case RENDERPATH_D3D9:
12705 case RENDERPATH_D3D10:
12706 case RENDERPATH_D3D11:
12707 RSurf_ActiveModelEntity(ent, true, true, false);
12709 case RENDERPATH_GL13:
12710 case RENDERPATH_GL11:
12711 RSurf_ActiveModelEntity(ent, true, false, false);
12716 if (r_transparentdepthmasking.integer)
12718 qboolean setup = false;
12719 for (i = 0;i < numsurfaces;i = j)
12722 surface = rsurface.modelsurfaces + surfacelist[i];
12723 texture = surface->texture;
12724 rsurface.texture = R_GetCurrentTexture(texture);
12725 rsurface.lightmaptexture = NULL;
12726 rsurface.deluxemaptexture = NULL;
12727 rsurface.uselightmaptexture = false;
12728 // scan ahead until we find a different texture
12729 endsurface = min(i + 1024, numsurfaces);
12730 texturenumsurfaces = 0;
12731 texturesurfacelist[texturenumsurfaces++] = surface;
12732 for (;j < endsurface;j++)
12734 surface = rsurface.modelsurfaces + surfacelist[j];
12735 if (texture != surface->texture)
12737 texturesurfacelist[texturenumsurfaces++] = surface;
12739 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12741 // render the range of surfaces as depth
12745 GL_ColorMask(0,0,0,0);
12747 GL_DepthTest(true);
12748 GL_BlendFunc(GL_ONE, GL_ZERO);
12749 GL_DepthMask(true);
12750 GL_AlphaTest(false);
12751 R_Mesh_ResetTextureState();
12752 R_SetupShader_DepthOrShadow();
12754 RSurf_SetupDepthAndCulling();
12755 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12756 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12760 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12763 for (i = 0;i < numsurfaces;i = j)
12766 surface = rsurface.modelsurfaces + surfacelist[i];
12767 texture = surface->texture;
12768 rsurface.texture = R_GetCurrentTexture(texture);
12769 rsurface.lightmaptexture = surface->lightmaptexture;
12770 rsurface.deluxemaptexture = surface->deluxemaptexture;
12771 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12772 // scan ahead until we find a different texture
12773 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12774 texturenumsurfaces = 0;
12775 texturesurfacelist[texturenumsurfaces++] = surface;
12776 for (;j < endsurface;j++)
12778 surface = rsurface.modelsurfaces + surfacelist[j];
12779 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12781 texturesurfacelist[texturenumsurfaces++] = surface;
12783 // render the range of surfaces
12784 if (ent == r_refdef.scene.worldentity)
12785 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12787 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12789 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12790 GL_AlphaTest(false);
12793 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12795 // transparent surfaces get pushed off into the transparent queue
12796 int surfacelistindex;
12797 const msurface_t *surface;
12798 vec3_t tempcenter, center;
12799 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12801 surface = texturesurfacelist[surfacelistindex];
12802 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12803 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12804 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12805 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12806 if (queueentity->transparent_offset) // transparent offset
12808 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12809 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12810 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12812 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12816 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12818 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12820 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12822 RSurf_SetupDepthAndCulling();
12823 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12824 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12828 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12830 const entity_render_t *queueentity = r_refdef.scene.worldentity;
12833 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12836 if (!rsurface.texture->currentnumlayers)
12838 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12839 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12841 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12843 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12844 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12845 else if (!rsurface.texture->currentnumlayers)
12847 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12849 // in the deferred case, transparent surfaces were queued during prepass
12850 if (!r_shadow_usingdeferredprepass)
12851 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12855 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12856 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12861 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12864 texture_t *texture;
12865 // break the surface list down into batches by texture and use of lightmapping
12866 for (i = 0;i < numsurfaces;i = j)
12869 // texture is the base texture pointer, rsurface.texture is the
12870 // current frame/skin the texture is directing us to use (for example
12871 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12872 // use skin 1 instead)
12873 texture = surfacelist[i]->texture;
12874 rsurface.texture = R_GetCurrentTexture(texture);
12875 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12876 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12877 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12878 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12880 // if this texture is not the kind we want, skip ahead to the next one
12881 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12885 // simply scan ahead until we find a different texture or lightmap state
12886 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12888 // render the range of surfaces
12889 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12893 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12897 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12900 if (!rsurface.texture->currentnumlayers)
12902 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12903 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12905 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12907 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12908 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12909 else if (!rsurface.texture->currentnumlayers)
12911 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12913 // in the deferred case, transparent surfaces were queued during prepass
12914 if (!r_shadow_usingdeferredprepass)
12915 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12919 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12920 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12925 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12928 texture_t *texture;
12929 // break the surface list down into batches by texture and use of lightmapping
12930 for (i = 0;i < numsurfaces;i = j)
12933 // texture is the base texture pointer, rsurface.texture is the
12934 // current frame/skin the texture is directing us to use (for example
12935 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12936 // use skin 1 instead)
12937 texture = surfacelist[i]->texture;
12938 rsurface.texture = R_GetCurrentTexture(texture);
12939 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12940 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12941 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12942 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12944 // if this texture is not the kind we want, skip ahead to the next one
12945 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12949 // simply scan ahead until we find a different texture or lightmap state
12950 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12952 // render the range of surfaces
12953 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12957 float locboxvertex3f[6*4*3] =
12959 1,0,1, 1,0,0, 1,1,0, 1,1,1,
12960 0,1,1, 0,1,0, 0,0,0, 0,0,1,
12961 1,1,1, 1,1,0, 0,1,0, 0,1,1,
12962 0,0,1, 0,0,0, 1,0,0, 1,0,1,
12963 0,0,1, 1,0,1, 1,1,1, 0,1,1,
12964 1,0,0, 0,0,0, 0,1,0, 1,1,0
12967 unsigned short locboxelements[6*2*3] =
12972 12,13,14, 12,14,15,
12973 16,17,18, 16,18,19,
12977 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12980 cl_locnode_t *loc = (cl_locnode_t *)ent;
12982 float vertex3f[6*4*3];
12984 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12985 GL_DepthMask(false);
12986 GL_DepthRange(0, 1);
12987 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12988 GL_DepthTest(true);
12989 GL_CullFace(GL_NONE);
12990 R_EntityMatrix(&identitymatrix);
12992 R_Mesh_ResetTextureState();
12994 i = surfacelist[0];
12995 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12996 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12997 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12998 surfacelist[0] < 0 ? 0.5f : 0.125f);
13000 if (VectorCompare(loc->mins, loc->maxs))
13002 VectorSet(size, 2, 2, 2);
13003 VectorMA(loc->mins, -0.5f, size, mins);
13007 VectorCopy(loc->mins, mins);
13008 VectorSubtract(loc->maxs, loc->mins, size);
13011 for (i = 0;i < 6*4*3;)
13012 for (j = 0;j < 3;j++, i++)
13013 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13015 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13016 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13017 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13020 void R_DrawLocs(void)
13023 cl_locnode_t *loc, *nearestloc;
13025 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13026 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13028 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13029 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13033 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13035 if (decalsystem->decals)
13036 Mem_Free(decalsystem->decals);
13037 memset(decalsystem, 0, sizeof(*decalsystem));
13040 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)
13043 tridecal_t *decals;
13046 // expand or initialize the system
13047 if (decalsystem->maxdecals <= decalsystem->numdecals)
13049 decalsystem_t old = *decalsystem;
13050 qboolean useshortelements;
13051 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13052 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13053 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)));
13054 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13055 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13056 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13057 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13058 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13059 if (decalsystem->numdecals)
13060 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13062 Mem_Free(old.decals);
13063 for (i = 0;i < decalsystem->maxdecals*3;i++)
13064 decalsystem->element3i[i] = i;
13065 if (useshortelements)
13066 for (i = 0;i < decalsystem->maxdecals*3;i++)
13067 decalsystem->element3s[i] = i;
13070 // grab a decal and search for another free slot for the next one
13071 decals = decalsystem->decals;
13072 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13073 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13075 decalsystem->freedecal = i;
13076 if (decalsystem->numdecals <= i)
13077 decalsystem->numdecals = i + 1;
13079 // initialize the decal
13081 decal->triangleindex = triangleindex;
13082 decal->surfaceindex = surfaceindex;
13083 decal->decalsequence = decalsequence;
13084 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13085 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13086 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13087 decal->color4ub[0][3] = 255;
13088 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13089 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13090 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13091 decal->color4ub[1][3] = 255;
13092 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13093 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13094 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13095 decal->color4ub[2][3] = 255;
13096 decal->vertex3f[0][0] = v0[0];
13097 decal->vertex3f[0][1] = v0[1];
13098 decal->vertex3f[0][2] = v0[2];
13099 decal->vertex3f[1][0] = v1[0];
13100 decal->vertex3f[1][1] = v1[1];
13101 decal->vertex3f[1][2] = v1[2];
13102 decal->vertex3f[2][0] = v2[0];
13103 decal->vertex3f[2][1] = v2[1];
13104 decal->vertex3f[2][2] = v2[2];
13105 decal->texcoord2f[0][0] = t0[0];
13106 decal->texcoord2f[0][1] = t0[1];
13107 decal->texcoord2f[1][0] = t1[0];
13108 decal->texcoord2f[1][1] = t1[1];
13109 decal->texcoord2f[2][0] = t2[0];
13110 decal->texcoord2f[2][1] = t2[1];
13113 extern cvar_t cl_decals_bias;
13114 extern cvar_t cl_decals_models;
13115 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13116 // baseparms, parms, temps
13117 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)
13122 const float *vertex3f;
13124 float points[2][9][3];
13131 e = rsurface.modelelement3i + 3*triangleindex;
13133 vertex3f = rsurface.modelvertex3f;
13135 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13137 index = 3*e[cornerindex];
13138 VectorCopy(vertex3f + index, v[cornerindex]);
13141 //TriangleNormal(v[0], v[1], v[2], normal);
13142 //if (DotProduct(normal, localnormal) < 0.0f)
13144 // clip by each of the box planes formed from the projection matrix
13145 // if anything survives, we emit the decal
13146 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]);
13149 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]);
13152 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]);
13155 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]);
13158 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]);
13161 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]);
13164 // some part of the triangle survived, so we have to accept it...
13167 // dynamic always uses the original triangle
13169 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13171 index = 3*e[cornerindex];
13172 VectorCopy(vertex3f + index, v[cornerindex]);
13175 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13177 // convert vertex positions to texcoords
13178 Matrix4x4_Transform(projection, v[cornerindex], temp);
13179 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13180 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13181 // calculate distance fade from the projection origin
13182 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13183 f = bound(0.0f, f, 1.0f);
13184 c[cornerindex][0] = r * f;
13185 c[cornerindex][1] = g * f;
13186 c[cornerindex][2] = b * f;
13187 c[cornerindex][3] = 1.0f;
13188 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13191 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);
13193 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13194 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);
13196 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)
13198 matrix4x4_t projection;
13199 decalsystem_t *decalsystem;
13202 const msurface_t *surface;
13203 const msurface_t *surfaces;
13204 const int *surfacelist;
13205 const texture_t *texture;
13207 int numsurfacelist;
13208 int surfacelistindex;
13211 float localorigin[3];
13212 float localnormal[3];
13213 float localmins[3];
13214 float localmaxs[3];
13217 float planes[6][4];
13220 int bih_triangles_count;
13221 int bih_triangles[256];
13222 int bih_surfaces[256];
13224 decalsystem = &ent->decalsystem;
13225 model = ent->model;
13226 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13228 R_DecalSystem_Reset(&ent->decalsystem);
13232 if (!model->brush.data_leafs && !cl_decals_models.integer)
13234 if (decalsystem->model)
13235 R_DecalSystem_Reset(decalsystem);
13239 if (decalsystem->model != model)
13240 R_DecalSystem_Reset(decalsystem);
13241 decalsystem->model = model;
13243 RSurf_ActiveModelEntity(ent, false, false, false);
13245 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13246 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13247 VectorNormalize(localnormal);
13248 localsize = worldsize*rsurface.inversematrixscale;
13249 localmins[0] = localorigin[0] - localsize;
13250 localmins[1] = localorigin[1] - localsize;
13251 localmins[2] = localorigin[2] - localsize;
13252 localmaxs[0] = localorigin[0] + localsize;
13253 localmaxs[1] = localorigin[1] + localsize;
13254 localmaxs[2] = localorigin[2] + localsize;
13256 //VectorCopy(localnormal, planes[4]);
13257 //VectorVectors(planes[4], planes[2], planes[0]);
13258 AnglesFromVectors(angles, localnormal, NULL, false);
13259 AngleVectors(angles, planes[0], planes[2], planes[4]);
13260 VectorNegate(planes[0], planes[1]);
13261 VectorNegate(planes[2], planes[3]);
13262 VectorNegate(planes[4], planes[5]);
13263 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13264 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13265 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13266 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13267 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13268 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13273 matrix4x4_t forwardprojection;
13274 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13275 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13280 float projectionvector[4][3];
13281 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13282 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13283 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13284 projectionvector[0][0] = planes[0][0] * ilocalsize;
13285 projectionvector[0][1] = planes[1][0] * ilocalsize;
13286 projectionvector[0][2] = planes[2][0] * ilocalsize;
13287 projectionvector[1][0] = planes[0][1] * ilocalsize;
13288 projectionvector[1][1] = planes[1][1] * ilocalsize;
13289 projectionvector[1][2] = planes[2][1] * ilocalsize;
13290 projectionvector[2][0] = planes[0][2] * ilocalsize;
13291 projectionvector[2][1] = planes[1][2] * ilocalsize;
13292 projectionvector[2][2] = planes[2][2] * ilocalsize;
13293 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13294 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13295 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13296 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13300 dynamic = model->surfmesh.isanimated;
13301 numsurfacelist = model->nummodelsurfaces;
13302 surfacelist = model->sortedmodelsurfaces;
13303 surfaces = model->data_surfaces;
13306 bih_triangles_count = -1;
13309 if(model->render_bih.numleafs)
13310 bih = &model->render_bih;
13311 else if(model->collision_bih.numleafs)
13312 bih = &model->collision_bih;
13315 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13316 if(bih_triangles_count == 0)
13318 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13320 if(bih_triangles_count > 0)
13322 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13324 surfaceindex = bih_surfaces[triangleindex];
13325 surface = surfaces + surfaceindex;
13326 texture = surface->texture;
13327 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13329 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13331 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13336 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13338 surfaceindex = surfacelist[surfacelistindex];
13339 surface = surfaces + surfaceindex;
13340 // check cull box first because it rejects more than any other check
13341 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13343 // skip transparent surfaces
13344 texture = surface->texture;
13345 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13347 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13349 numtriangles = surface->num_triangles;
13350 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13351 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13356 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13357 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)
13359 int renderentityindex;
13360 float worldmins[3];
13361 float worldmaxs[3];
13362 entity_render_t *ent;
13364 if (!cl_decals_newsystem.integer)
13367 worldmins[0] = worldorigin[0] - worldsize;
13368 worldmins[1] = worldorigin[1] - worldsize;
13369 worldmins[2] = worldorigin[2] - worldsize;
13370 worldmaxs[0] = worldorigin[0] + worldsize;
13371 worldmaxs[1] = worldorigin[1] + worldsize;
13372 worldmaxs[2] = worldorigin[2] + worldsize;
13374 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13376 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13378 ent = r_refdef.scene.entities[renderentityindex];
13379 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13382 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13386 typedef struct r_decalsystem_splatqueue_s
13388 vec3_t worldorigin;
13389 vec3_t worldnormal;
13395 r_decalsystem_splatqueue_t;
13397 int r_decalsystem_numqueued = 0;
13398 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13400 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)
13402 r_decalsystem_splatqueue_t *queue;
13404 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13407 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13408 VectorCopy(worldorigin, queue->worldorigin);
13409 VectorCopy(worldnormal, queue->worldnormal);
13410 Vector4Set(queue->color, r, g, b, a);
13411 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13412 queue->worldsize = worldsize;
13413 queue->decalsequence = cl.decalsequence++;
13416 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13419 r_decalsystem_splatqueue_t *queue;
13421 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13422 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);
13423 r_decalsystem_numqueued = 0;
13426 extern cvar_t cl_decals_max;
13427 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13430 decalsystem_t *decalsystem = &ent->decalsystem;
13437 if (!decalsystem->numdecals)
13440 if (r_showsurfaces.integer)
13443 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13445 R_DecalSystem_Reset(decalsystem);
13449 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13450 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13452 if (decalsystem->lastupdatetime)
13453 frametime = (cl.time - decalsystem->lastupdatetime);
13456 decalsystem->lastupdatetime = cl.time;
13457 decal = decalsystem->decals;
13458 numdecals = decalsystem->numdecals;
13460 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13462 if (decal->color4ub[0][3])
13464 decal->lived += frametime;
13465 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13467 memset(decal, 0, sizeof(*decal));
13468 if (decalsystem->freedecal > i)
13469 decalsystem->freedecal = i;
13473 decal = decalsystem->decals;
13474 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13477 // collapse the array by shuffling the tail decals into the gaps
13480 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13481 decalsystem->freedecal++;
13482 if (decalsystem->freedecal == numdecals)
13484 decal[decalsystem->freedecal] = decal[--numdecals];
13487 decalsystem->numdecals = numdecals;
13489 if (numdecals <= 0)
13491 // if there are no decals left, reset decalsystem
13492 R_DecalSystem_Reset(decalsystem);
13496 extern skinframe_t *decalskinframe;
13497 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13500 decalsystem_t *decalsystem = &ent->decalsystem;
13509 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13512 numdecals = decalsystem->numdecals;
13516 if (r_showsurfaces.integer)
13519 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13521 R_DecalSystem_Reset(decalsystem);
13525 // if the model is static it doesn't matter what value we give for
13526 // wantnormals and wanttangents, so this logic uses only rules applicable
13527 // to a model, knowing that they are meaningless otherwise
13528 if (ent == r_refdef.scene.worldentity)
13529 RSurf_ActiveWorldEntity();
13531 RSurf_ActiveModelEntity(ent, false, false, false);
13533 decalsystem->lastupdatetime = cl.time;
13534 decal = decalsystem->decals;
13536 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13538 // update vertex positions for animated models
13539 v3f = decalsystem->vertex3f;
13540 c4f = decalsystem->color4f;
13541 t2f = decalsystem->texcoord2f;
13542 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13544 if (!decal->color4ub[0][3])
13547 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13550 // update color values for fading decals
13551 if (decal->lived >= cl_decals_time.value)
13553 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13554 alpha *= (1.0f/255.0f);
13557 alpha = 1.0f/255.0f;
13559 c4f[ 0] = decal->color4ub[0][0] * alpha;
13560 c4f[ 1] = decal->color4ub[0][1] * alpha;
13561 c4f[ 2] = decal->color4ub[0][2] * alpha;
13563 c4f[ 4] = decal->color4ub[1][0] * alpha;
13564 c4f[ 5] = decal->color4ub[1][1] * alpha;
13565 c4f[ 6] = decal->color4ub[1][2] * alpha;
13567 c4f[ 8] = decal->color4ub[2][0] * alpha;
13568 c4f[ 9] = decal->color4ub[2][1] * alpha;
13569 c4f[10] = decal->color4ub[2][2] * alpha;
13572 t2f[0] = decal->texcoord2f[0][0];
13573 t2f[1] = decal->texcoord2f[0][1];
13574 t2f[2] = decal->texcoord2f[1][0];
13575 t2f[3] = decal->texcoord2f[1][1];
13576 t2f[4] = decal->texcoord2f[2][0];
13577 t2f[5] = decal->texcoord2f[2][1];
13579 // update vertex positions for animated models
13580 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13582 e = rsurface.modelelement3i + 3*decal->triangleindex;
13583 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13584 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13585 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13589 VectorCopy(decal->vertex3f[0], v3f);
13590 VectorCopy(decal->vertex3f[1], v3f + 3);
13591 VectorCopy(decal->vertex3f[2], v3f + 6);
13594 if (r_refdef.fogenabled)
13596 alpha = RSurf_FogVertex(v3f);
13597 VectorScale(c4f, alpha, c4f);
13598 alpha = RSurf_FogVertex(v3f + 3);
13599 VectorScale(c4f + 4, alpha, c4f + 4);
13600 alpha = RSurf_FogVertex(v3f + 6);
13601 VectorScale(c4f + 8, alpha, c4f + 8);
13612 r_refdef.stats.drawndecals += numtris;
13614 // now render the decals all at once
13615 // (this assumes they all use one particle font texture!)
13616 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);
13617 R_Mesh_ResetTextureState();
13618 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13619 GL_DepthMask(false);
13620 GL_DepthRange(0, 1);
13621 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13622 GL_DepthTest(true);
13623 GL_CullFace(GL_NONE);
13624 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13625 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13626 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13630 static void R_DrawModelDecals(void)
13634 // fade faster when there are too many decals
13635 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13636 for (i = 0;i < r_refdef.scene.numentities;i++)
13637 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13639 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13640 for (i = 0;i < r_refdef.scene.numentities;i++)
13641 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13642 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13644 R_DecalSystem_ApplySplatEntitiesQueue();
13646 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13647 for (i = 0;i < r_refdef.scene.numentities;i++)
13648 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13650 r_refdef.stats.totaldecals += numdecals;
13652 if (r_showsurfaces.integer)
13655 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13657 for (i = 0;i < r_refdef.scene.numentities;i++)
13659 if (!r_refdef.viewcache.entityvisible[i])
13661 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13662 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13666 extern cvar_t mod_collision_bih;
13667 void R_DrawDebugModel(void)
13669 entity_render_t *ent = rsurface.entity;
13670 int i, j, k, l, flagsmask;
13671 const msurface_t *surface;
13672 dp_model_t *model = ent->model;
13675 switch(vid.renderpath)
13677 case RENDERPATH_GL11:
13678 case RENDERPATH_GL13:
13679 case RENDERPATH_GL20:
13680 case RENDERPATH_CGGL:
13682 case RENDERPATH_D3D9:
13683 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13685 case RENDERPATH_D3D10:
13686 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13688 case RENDERPATH_D3D11:
13689 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13693 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13695 R_Mesh_ResetTextureState();
13696 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13697 GL_DepthRange(0, 1);
13698 GL_DepthTest(!r_showdisabledepthtest.integer);
13699 GL_DepthMask(false);
13700 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13702 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13706 qboolean cullbox = ent == r_refdef.scene.worldentity;
13707 const q3mbrush_t *brush;
13708 const bih_t *bih = &model->collision_bih;
13709 const bih_leaf_t *bihleaf;
13710 float vertex3f[3][3];
13711 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13713 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13715 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13717 switch (bihleaf->type)
13720 brush = model->brush.data_brushes + bihleaf->itemindex;
13721 if (brush->colbrushf && brush->colbrushf->numtriangles)
13723 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);
13724 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13725 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13728 case BIH_COLLISIONTRIANGLE:
13729 triangleindex = bihleaf->itemindex;
13730 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13731 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13732 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13733 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);
13734 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13735 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13737 case BIH_RENDERTRIANGLE:
13738 triangleindex = bihleaf->itemindex;
13739 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13740 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13741 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13742 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);
13743 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13744 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13750 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13752 if (r_showtris.integer || r_shownormals.integer)
13754 if (r_showdisabledepthtest.integer)
13756 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13757 GL_DepthMask(false);
13761 GL_BlendFunc(GL_ONE, GL_ZERO);
13762 GL_DepthMask(true);
13764 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13766 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13768 rsurface.texture = R_GetCurrentTexture(surface->texture);
13769 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13771 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13772 if (r_showtris.value > 0)
13774 if (!rsurface.texture->currentlayers->depthmask)
13775 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13776 else if (ent == r_refdef.scene.worldentity)
13777 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13779 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13780 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13781 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13783 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13786 if (r_shownormals.value < 0)
13788 qglBegin(GL_LINES);
13789 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13791 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13792 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13793 qglVertex3f(v[0], v[1], v[2]);
13794 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13795 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13796 qglVertex3f(v[0], v[1], v[2]);
13801 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13803 qglBegin(GL_LINES);
13804 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13806 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13807 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13808 qglVertex3f(v[0], v[1], v[2]);
13809 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13810 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13811 qglVertex3f(v[0], v[1], v[2]);
13815 qglBegin(GL_LINES);
13816 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13818 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13819 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13820 qglVertex3f(v[0], v[1], v[2]);
13821 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13822 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13823 qglVertex3f(v[0], v[1], v[2]);
13827 qglBegin(GL_LINES);
13828 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13830 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13831 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13832 qglVertex3f(v[0], v[1], v[2]);
13833 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13834 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13835 qglVertex3f(v[0], v[1], v[2]);
13842 rsurface.texture = NULL;
13846 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13847 int r_maxsurfacelist = 0;
13848 const msurface_t **r_surfacelist = NULL;
13849 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13851 int i, j, endj, flagsmask;
13852 dp_model_t *model = r_refdef.scene.worldmodel;
13853 msurface_t *surfaces;
13854 unsigned char *update;
13855 int numsurfacelist = 0;
13859 if (r_maxsurfacelist < model->num_surfaces)
13861 r_maxsurfacelist = model->num_surfaces;
13863 Mem_Free((msurface_t**)r_surfacelist);
13864 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13867 RSurf_ActiveWorldEntity();
13869 surfaces = model->data_surfaces;
13870 update = model->brushq1.lightmapupdateflags;
13872 // update light styles on this submodel
13873 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13875 model_brush_lightstyleinfo_t *style;
13876 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13878 if (style->value != r_refdef.scene.lightstylevalue[style->style])
13880 int *list = style->surfacelist;
13881 style->value = r_refdef.scene.lightstylevalue[style->style];
13882 for (j = 0;j < style->numsurfaces;j++)
13883 update[list[j]] = true;
13888 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13892 R_DrawDebugModel();
13893 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13897 rsurface.lightmaptexture = NULL;
13898 rsurface.deluxemaptexture = NULL;
13899 rsurface.uselightmaptexture = false;
13900 rsurface.texture = NULL;
13901 rsurface.rtlight = NULL;
13902 numsurfacelist = 0;
13903 // add visible surfaces to draw list
13904 for (i = 0;i < model->nummodelsurfaces;i++)
13906 j = model->sortedmodelsurfaces[i];
13907 if (r_refdef.viewcache.world_surfacevisible[j])
13908 r_surfacelist[numsurfacelist++] = surfaces + j;
13910 // update lightmaps if needed
13911 if (model->brushq1.firstrender)
13913 model->brushq1.firstrender = false;
13914 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13916 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13920 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13921 if (r_refdef.viewcache.world_surfacevisible[j])
13923 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13925 // don't do anything if there were no surfaces
13926 if (!numsurfacelist)
13928 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13931 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13932 GL_AlphaTest(false);
13934 // add to stats if desired
13935 if (r_speeds.integer && !skysurfaces && !depthonly)
13937 r_refdef.stats.world_surfaces += numsurfacelist;
13938 for (j = 0;j < numsurfacelist;j++)
13939 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13942 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13945 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13947 int i, j, endj, flagsmask;
13948 dp_model_t *model = ent->model;
13949 msurface_t *surfaces;
13950 unsigned char *update;
13951 int numsurfacelist = 0;
13955 if (r_maxsurfacelist < model->num_surfaces)
13957 r_maxsurfacelist = model->num_surfaces;
13959 Mem_Free((msurface_t **)r_surfacelist);
13960 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13963 // if the model is static it doesn't matter what value we give for
13964 // wantnormals and wanttangents, so this logic uses only rules applicable
13965 // to a model, knowing that they are meaningless otherwise
13966 if (ent == r_refdef.scene.worldentity)
13967 RSurf_ActiveWorldEntity();
13968 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13969 RSurf_ActiveModelEntity(ent, false, false, false);
13971 RSurf_ActiveModelEntity(ent, true, true, true);
13972 else if (depthonly)
13974 switch (vid.renderpath)
13976 case RENDERPATH_GL20:
13977 case RENDERPATH_CGGL:
13978 case RENDERPATH_D3D9:
13979 case RENDERPATH_D3D10:
13980 case RENDERPATH_D3D11:
13981 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13983 case RENDERPATH_GL13:
13984 case RENDERPATH_GL11:
13985 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13991 switch (vid.renderpath)
13993 case RENDERPATH_GL20:
13994 case RENDERPATH_CGGL:
13995 case RENDERPATH_D3D9:
13996 case RENDERPATH_D3D10:
13997 case RENDERPATH_D3D11:
13998 RSurf_ActiveModelEntity(ent, true, true, false);
14000 case RENDERPATH_GL13:
14001 case RENDERPATH_GL11:
14002 RSurf_ActiveModelEntity(ent, true, false, false);
14007 surfaces = model->data_surfaces;
14008 update = model->brushq1.lightmapupdateflags;
14010 // update light styles
14011 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14013 model_brush_lightstyleinfo_t *style;
14014 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14016 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14018 int *list = style->surfacelist;
14019 style->value = r_refdef.scene.lightstylevalue[style->style];
14020 for (j = 0;j < style->numsurfaces;j++)
14021 update[list[j]] = true;
14026 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14030 R_DrawDebugModel();
14031 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14035 rsurface.lightmaptexture = NULL;
14036 rsurface.deluxemaptexture = NULL;
14037 rsurface.uselightmaptexture = false;
14038 rsurface.texture = NULL;
14039 rsurface.rtlight = NULL;
14040 numsurfacelist = 0;
14041 // add visible surfaces to draw list
14042 for (i = 0;i < model->nummodelsurfaces;i++)
14043 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14044 // don't do anything if there were no surfaces
14045 if (!numsurfacelist)
14047 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14050 // update lightmaps if needed
14054 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14059 R_BuildLightMap(ent, surfaces + j);
14064 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14066 R_BuildLightMap(ent, surfaces + j);
14067 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14068 GL_AlphaTest(false);
14070 // add to stats if desired
14071 if (r_speeds.integer && !skysurfaces && !depthonly)
14073 r_refdef.stats.entities_surfaces += numsurfacelist;
14074 for (j = 0;j < numsurfacelist;j++)
14075 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14078 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14081 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14083 static texture_t texture;
14084 static msurface_t surface;
14085 const msurface_t *surfacelist = &surface;
14087 // fake enough texture and surface state to render this geometry
14089 texture.update_lastrenderframe = -1; // regenerate this texture
14090 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14091 texture.currentskinframe = skinframe;
14092 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14093 texture.offsetmapping = OFFSETMAPPING_OFF;
14094 texture.offsetscale = 1;
14095 texture.specularscalemod = 1;
14096 texture.specularpowermod = 1;
14098 surface.texture = &texture;
14099 surface.num_triangles = numtriangles;
14100 surface.num_firsttriangle = firsttriangle;
14101 surface.num_vertices = numvertices;
14102 surface.num_firstvertex = firstvertex;
14105 rsurface.texture = R_GetCurrentTexture(surface.texture);
14106 rsurface.lightmaptexture = NULL;
14107 rsurface.deluxemaptexture = NULL;
14108 rsurface.uselightmaptexture = false;
14109 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14112 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)
14114 static msurface_t surface;
14115 const msurface_t *surfacelist = &surface;
14117 // fake enough texture and surface state to render this geometry
14119 surface.texture = texture;
14120 surface.num_triangles = numtriangles;
14121 surface.num_firsttriangle = firsttriangle;
14122 surface.num_vertices = numvertices;
14123 surface.num_firstvertex = firstvertex;
14126 rsurface.texture = R_GetCurrentTexture(surface.texture);
14127 rsurface.lightmaptexture = NULL;
14128 rsurface.deluxemaptexture = NULL;
14129 rsurface.uselightmaptexture = false;
14130 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);