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"};
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 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."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 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."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 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"};
113 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"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 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"};
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129 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)"};
130 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"};
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142 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)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 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)"};
148 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)"};
149 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)"};
150 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)"};
152 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)"};
153 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
154 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"};
155 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
156 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
157 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
159 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
160 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
161 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
162 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
164 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
165 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
166 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
167 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
168 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
169 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
170 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
172 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
173 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
174 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
175 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)"};
177 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"};
179 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"};
181 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
183 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
184 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"};
185 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
186 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
187 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
188 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
189 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)"};
191 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
192 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
194 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)"};
196 extern cvar_t v_glslgamma;
198 extern qboolean v_flipped_state;
200 static struct r_bloomstate_s
205 int bloomwidth, bloomheight;
207 int screentexturewidth, screentextureheight;
208 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
210 int bloomtexturewidth, bloomtextureheight;
211 rtexture_t *texture_bloom;
213 // arrays for rendering the screen passes
214 float screentexcoord2f[8];
215 float bloomtexcoord2f[8];
216 float offsettexcoord2f[8];
218 r_viewport_t viewport;
222 r_waterstate_t r_waterstate;
224 /// shadow volume bsp struct with automatically growing nodes buffer
227 rtexture_t *r_texture_blanknormalmap;
228 rtexture_t *r_texture_white;
229 rtexture_t *r_texture_grey128;
230 rtexture_t *r_texture_black;
231 rtexture_t *r_texture_notexture;
232 rtexture_t *r_texture_whitecube;
233 rtexture_t *r_texture_normalizationcube;
234 rtexture_t *r_texture_fogattenuation;
235 rtexture_t *r_texture_fogheighttexture;
236 rtexture_t *r_texture_gammaramps;
237 unsigned int r_texture_gammaramps_serial;
238 //rtexture_t *r_texture_fogintensity;
239 rtexture_t *r_texture_reflectcube;
241 // TODO: hash lookups?
242 typedef struct cubemapinfo_s
249 int r_texture_numcubemaps;
250 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
252 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
253 unsigned int r_numqueries;
254 unsigned int r_maxqueries;
256 typedef struct r_qwskincache_s
258 char name[MAX_QPATH];
259 skinframe_t *skinframe;
263 static r_qwskincache_t *r_qwskincache;
264 static int r_qwskincache_size;
266 /// vertex coordinates for a quad that covers the screen exactly
267 extern const float r_screenvertex3f[12];
268 extern const float r_d3dscreenvertex3f[12];
269 const float r_screenvertex3f[12] =
276 const float r_d3dscreenvertex3f[12] =
284 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
287 for (i = 0;i < verts;i++)
298 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
301 for (i = 0;i < verts;i++)
311 // FIXME: move this to client?
314 if (gamemode == GAME_NEHAHRA)
316 Cvar_Set("gl_fogenable", "0");
317 Cvar_Set("gl_fogdensity", "0.2");
318 Cvar_Set("gl_fogred", "0.3");
319 Cvar_Set("gl_foggreen", "0.3");
320 Cvar_Set("gl_fogblue", "0.3");
322 r_refdef.fog_density = 0;
323 r_refdef.fog_red = 0;
324 r_refdef.fog_green = 0;
325 r_refdef.fog_blue = 0;
326 r_refdef.fog_alpha = 1;
327 r_refdef.fog_start = 0;
328 r_refdef.fog_end = 16384;
329 r_refdef.fog_height = 1<<30;
330 r_refdef.fog_fadedepth = 128;
331 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
334 static void R_BuildBlankTextures(void)
336 unsigned char data[4];
337 data[2] = 128; // normal X
338 data[1] = 128; // normal Y
339 data[0] = 255; // normal Z
340 data[3] = 128; // height
341 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 static void R_BuildNoTexture(void)
362 unsigned char pix[16][16][4];
363 // this makes a light grey/dark grey checkerboard texture
364 for (y = 0;y < 16;y++)
366 for (x = 0;x < 16;x++)
368 if ((y < 8) ^ (x < 8))
384 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
387 static void R_BuildWhiteCube(void)
389 unsigned char data[6*1*1*4];
390 memset(data, 255, sizeof(data));
391 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNormalizationCube(void)
398 vec_t s, t, intensity;
401 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
402 for (side = 0;side < 6;side++)
404 for (y = 0;y < NORMSIZE;y++)
406 for (x = 0;x < NORMSIZE;x++)
408 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
409 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 intensity = 127.0f / sqrt(DotProduct(v, v));
445 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
446 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
447 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
448 data[((side*64+y)*64+x)*4+3] = 255;
452 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
456 static void R_BuildFogTexture(void)
460 unsigned char data1[FOGWIDTH][4];
461 //unsigned char data2[FOGWIDTH][4];
464 r_refdef.fogmasktable_start = r_refdef.fog_start;
465 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
466 r_refdef.fogmasktable_range = r_refdef.fogrange;
467 r_refdef.fogmasktable_density = r_refdef.fog_density;
469 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
470 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
472 d = (x * r - r_refdef.fogmasktable_start);
473 if(developer_extra.integer)
474 Con_DPrintf("%f ", d);
476 if (r_fog_exp2.integer)
477 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
479 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
480 if(developer_extra.integer)
481 Con_DPrintf(" : %f ", alpha);
482 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
483 if(developer_extra.integer)
484 Con_DPrintf(" = %f\n", alpha);
485 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
488 for (x = 0;x < FOGWIDTH;x++)
490 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
495 //data2[x][0] = 255 - b;
496 //data2[x][1] = 255 - b;
497 //data2[x][2] = 255 - b;
500 if (r_texture_fogattenuation)
502 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
503 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
507 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
512 static void R_BuildFogHeightTexture(void)
514 unsigned char *inpixels;
522 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
523 if (r_refdef.fogheighttexturename[0])
524 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
527 r_refdef.fog_height_tablesize = 0;
528 if (r_texture_fogheighttexture)
529 R_FreeTexture(r_texture_fogheighttexture);
530 r_texture_fogheighttexture = NULL;
531 if (r_refdef.fog_height_table2d)
532 Mem_Free(r_refdef.fog_height_table2d);
533 r_refdef.fog_height_table2d = NULL;
534 if (r_refdef.fog_height_table1d)
535 Mem_Free(r_refdef.fog_height_table1d);
536 r_refdef.fog_height_table1d = NULL;
540 r_refdef.fog_height_tablesize = size;
541 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
542 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
543 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
545 // LordHavoc: now the magic - what is that table2d for? it is a cooked
546 // average fog color table accounting for every fog layer between a point
547 // and the camera. (Note: attenuation is handled separately!)
548 for (y = 0;y < size;y++)
550 for (x = 0;x < size;x++)
556 for (j = x;j <= y;j++)
558 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
564 for (j = x;j >= y;j--)
566 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
572 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
573 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
574 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
577 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
580 //=======================================================================================================================================================
582 static const char *builtinshaderstring =
583 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
584 "// written by Forest 'LordHavoc' Hale\n"
585 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
587 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
590 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
591 "#define USELIGHTMAP\n"
593 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
594 "#define USEEYEVECTOR\n"
597 "#ifdef USESHADOWMAP2D\n"
598 "# ifdef GL_EXT_gpu_shader4\n"
599 "# extension GL_EXT_gpu_shader4 : enable\n"
601 "# ifdef GL_ARB_texture_gather\n"
602 "# extension GL_ARB_texture_gather : enable\n"
604 "# ifdef GL_AMD_texture_texture4\n"
605 "# extension GL_AMD_texture_texture4 : enable\n"
610 "//#ifdef USESHADOWSAMPLER\n"
611 "//# extension GL_ARB_shadow : enable\n"
614 "//#ifdef __GLSL_CG_DATA_TYPES\n"
615 "//# define myhalf half\n"
616 "//# define myhalf2 half2\n"
617 "//# define myhalf3 half3\n"
618 "//# define myhalf4 half4\n"
620 "# define myhalf float\n"
621 "# define myhalf2 vec2\n"
622 "# define myhalf3 vec3\n"
623 "# define myhalf4 vec4\n"
626 "#ifdef VERTEX_SHADER\n"
627 "uniform mat4 ModelViewProjectionMatrix;\n"
630 "#ifdef MODE_DEPTH_OR_SHADOW\n"
631 "#ifdef VERTEX_SHADER\n"
634 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
637 "#else // !MODE_DEPTH_ORSHADOW\n"
642 "#ifdef MODE_SHOWDEPTH\n"
643 "#ifdef VERTEX_SHADER\n"
646 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
647 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
651 "#ifdef FRAGMENT_SHADER\n"
654 " gl_FragColor = gl_Color;\n"
657 "#else // !MODE_SHOWDEPTH\n"
662 "#ifdef MODE_POSTPROCESS\n"
663 "varying vec2 TexCoord1;\n"
664 "varying vec2 TexCoord2;\n"
666 "#ifdef VERTEX_SHADER\n"
669 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
670 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
677 "#ifdef FRAGMENT_SHADER\n"
678 "uniform sampler2D Texture_First;\n"
680 "uniform sampler2D Texture_Second;\n"
681 "uniform vec4 BloomColorSubtract;\n"
683 "#ifdef USEGAMMARAMPS\n"
684 "uniform sampler2D Texture_GammaRamps;\n"
686 "#ifdef USESATURATION\n"
687 "uniform float Saturation;\n"
689 "#ifdef USEVIEWTINT\n"
690 "uniform vec4 ViewTintColor;\n"
692 "//uncomment these if you want to use them:\n"
693 "uniform vec4 UserVec1;\n"
694 "uniform vec4 UserVec2;\n"
695 "// uniform vec4 UserVec3;\n"
696 "// uniform vec4 UserVec4;\n"
697 "// uniform float ClientTime;\n"
698 "uniform vec2 PixelSize;\n"
701 " gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 " gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#ifdef USEVIEWTINT\n"
706 " gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
709 "#ifdef USEPOSTPROCESSING\n"
710 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
711 "// 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"
712 " float sobel = 1.0;\n"
713 " // vec2 ts = textureSize(Texture_First, 0);\n"
714 " // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
715 " vec2 px = PixelSize;\n"
716 " vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
717 " vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, 0.0)).rgb;\n"
718 " vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
719 " vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
720 " vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x, 0.0)).rgb;\n"
721 " vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
722 " vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 " vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2( 0.0,-px.y)).rgb;\n"
724 " vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 " vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 " vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2( 0.0, px.y)).rgb;\n"
727 " vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
728 " float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
729 " float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
730 " float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
731 " float px4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
732 " float px5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
733 " float px6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
734 " float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
735 " float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
736 " float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
737 " float py4 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
738 " float py5 = 2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
739 " float py6 = 1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
740 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
741 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
742 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
743 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
744 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
745 " gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
746 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
747 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
750 "#ifdef USESATURATION\n"
751 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
752 " float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
753 " // 'vampire sight' effect, wheres red is compensated\n"
754 " #ifdef SATURATION_REDCOMPENSATE\n"
755 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
756 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
757 " gl_FragColor.r += rboost;\n"
759 " // normal desaturation\n"
760 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
761 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
765 "#ifdef USEGAMMARAMPS\n"
766 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
767 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
768 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
772 "#else // !MODE_POSTPROCESS\n"
777 "#ifdef MODE_GENERIC\n"
778 "#ifdef USEDIFFUSE\n"
779 "varying vec2 TexCoord1;\n"
781 "#ifdef USESPECULAR\n"
782 "varying vec2 TexCoord2;\n"
784 "#ifdef VERTEX_SHADER\n"
787 " gl_FrontColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
791 "#ifdef USESPECULAR\n"
792 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
794 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
798 "#ifdef FRAGMENT_SHADER\n"
799 "#ifdef USEDIFFUSE\n"
800 "uniform sampler2D Texture_First;\n"
802 "#ifdef USESPECULAR\n"
803 "uniform sampler2D Texture_Second;\n"
808 " gl_FragColor = gl_Color;\n"
809 "#ifdef USEDIFFUSE\n"
810 " gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
813 "#ifdef USESPECULAR\n"
814 " vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
815 "# ifdef USECOLORMAPPING\n"
816 " gl_FragColor *= tex2;\n"
819 " gl_FragColor += tex2;\n"
821 "# ifdef USEVERTEXTEXTUREBLEND\n"
822 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
827 "#else // !MODE_GENERIC\n"
832 "#ifdef MODE_BLOOMBLUR\n"
833 "varying TexCoord;\n"
834 "#ifdef VERTEX_SHADER\n"
837 " gl_FrontColor = gl_Color;\n"
838 " TexCoord = gl_MultiTexCoord0.xy;\n"
839 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
843 "#ifdef FRAGMENT_SHADER\n"
844 "uniform sampler2D Texture_First;\n"
845 "uniform vec4 BloomBlur_Parameters;\n"
850 " vec2 tc = TexCoord;\n"
851 " vec3 color = texture2D(Texture_First, tc).rgb;\n"
852 " tc += BloomBlur_Parameters.xy;\n"
853 " for (i = 1;i < SAMPLES;i++)\n"
855 " color += texture2D(Texture_First, tc).rgb;\n"
856 " tc += BloomBlur_Parameters.xy;\n"
858 " gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
861 "#else // !MODE_BLOOMBLUR\n"
862 "#ifdef MODE_REFRACTION\n"
863 "varying vec2 TexCoord;\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "#ifdef VERTEX_SHADER\n"
870 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
871 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
872 " ModelViewProjectionPosition = gl_Position;\n"
876 "#ifdef FRAGMENT_SHADER\n"
877 "uniform sampler2D Texture_Normal;\n"
878 "uniform sampler2D Texture_Refraction;\n"
879 "uniform sampler2D Texture_Reflection;\n"
881 "uniform vec4 DistortScaleRefractReflect;\n"
882 "uniform vec4 ScreenScaleRefractReflect;\n"
883 "uniform vec4 ScreenCenterRefractReflect;\n"
884 "uniform vec4 RefractColor;\n"
885 "uniform vec4 ReflectColor;\n"
886 "uniform float ReflectFactor;\n"
887 "uniform float ReflectOffset;\n"
891 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
892 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
893 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
894 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
895 " // FIXME temporary hack to detect the case that the reflection\n"
896 " // gets blackened at edges due to leaving the area that contains actual\n"
898 " // Remove this 'ack once we have a better way to stop this thing from\n"
900 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
901 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
902 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
903 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
904 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
905 " gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
908 "#else // !MODE_REFRACTION\n"
913 "#ifdef MODE_WATER\n"
914 "varying vec2 TexCoord;\n"
915 "varying vec3 EyeVector;\n"
916 "varying vec4 ModelViewProjectionPosition;\n"
917 "#ifdef VERTEX_SHADER\n"
918 "uniform vec3 EyePosition;\n"
919 "uniform mat4 TexMatrix;\n"
923 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
924 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
925 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
926 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
927 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
928 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
929 " ModelViewProjectionPosition = gl_Position;\n"
933 "#ifdef FRAGMENT_SHADER\n"
934 "uniform sampler2D Texture_Normal;\n"
935 "uniform sampler2D Texture_Refraction;\n"
936 "uniform sampler2D Texture_Reflection;\n"
938 "uniform vec4 DistortScaleRefractReflect;\n"
939 "uniform vec4 ScreenScaleRefractReflect;\n"
940 "uniform vec4 ScreenCenterRefractReflect;\n"
941 "uniform vec4 RefractColor;\n"
942 "uniform vec4 ReflectColor;\n"
943 "uniform float ReflectFactor;\n"
944 "uniform float ReflectOffset;\n"
945 "uniform float ClientTime;\n"
946 "#ifdef USENORMALMAPSCROLLBLEND\n"
947 "uniform vec2 NormalmapScrollBlend;\n"
952 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
953 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
954 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
955 " //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
956 " // slight water animation via 2 layer scrolling (todo: tweak)\n"
957 " #ifdef USENORMALMAPSCROLLBLEND\n"
958 " vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
959 " normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
960 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
962 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
964 " // FIXME temporary hack to detect the case that the reflection\n"
965 " // gets blackened at edges due to leaving the area that contains actual\n"
967 " // Remove this 'ack once we have a better way to stop this thing from\n"
969 " float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
970 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
971 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
972 " f1 *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
973 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
974 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
975 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
976 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
977 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
978 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
979 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
980 " gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
981 " gl_FragColor.a = f1 + 0.5;\n"
984 "#else // !MODE_WATER\n"
989 "// common definitions between vertex shader and fragment shader:\n"
991 "varying vec2 TexCoord;\n"
992 "#ifdef USEVERTEXTEXTUREBLEND\n"
993 "varying vec2 TexCoord2;\n"
995 "#ifdef USELIGHTMAP\n"
996 "varying vec2 TexCoordLightmap;\n"
999 "#ifdef MODE_LIGHTSOURCE\n"
1000 "varying vec3 CubeVector;\n"
1003 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1004 "varying vec3 LightVector;\n"
1007 "#ifdef USEEYEVECTOR\n"
1008 "varying vec3 EyeVector;\n"
1011 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1014 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1015 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1016 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1017 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1020 "#ifdef USEREFLECTION\n"
1021 "varying vec4 ModelViewProjectionPosition;\n"
1023 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1024 "uniform vec3 LightPosition;\n"
1025 "varying vec4 ModelViewPosition;\n"
1028 "#ifdef MODE_LIGHTSOURCE\n"
1029 "uniform vec3 LightPosition;\n"
1031 "uniform vec3 EyePosition;\n"
1032 "#ifdef MODE_LIGHTDIRECTION\n"
1033 "uniform vec3 LightDir;\n"
1035 "uniform vec4 FogPlane;\n"
1037 "#ifdef USESHADOWMAPORTHO\n"
1038 "varying vec3 ShadowMapTC;\n"
1045 "// 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"
1047 "// fragment shader specific:\n"
1048 "#ifdef FRAGMENT_SHADER\n"
1050 "uniform sampler2D Texture_Normal;\n"
1051 "uniform sampler2D Texture_Color;\n"
1052 "uniform sampler2D Texture_Gloss;\n"
1054 "uniform sampler2D Texture_Glow;\n"
1056 "#ifdef USEVERTEXTEXTUREBLEND\n"
1057 "uniform sampler2D Texture_SecondaryNormal;\n"
1058 "uniform sampler2D Texture_SecondaryColor;\n"
1059 "uniform sampler2D Texture_SecondaryGloss;\n"
1061 "uniform sampler2D Texture_SecondaryGlow;\n"
1064 "#ifdef USECOLORMAPPING\n"
1065 "uniform sampler2D Texture_Pants;\n"
1066 "uniform sampler2D Texture_Shirt;\n"
1069 "#ifdef USEFOGHEIGHTTEXTURE\n"
1070 "uniform sampler2D Texture_FogHeightTexture;\n"
1072 "uniform sampler2D Texture_FogMask;\n"
1074 "#ifdef USELIGHTMAP\n"
1075 "uniform sampler2D Texture_Lightmap;\n"
1077 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1078 "uniform sampler2D Texture_Deluxemap;\n"
1080 "#ifdef USEREFLECTION\n"
1081 "uniform sampler2D Texture_Reflection;\n"
1084 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1085 "uniform sampler2D Texture_ScreenDepth;\n"
1086 "uniform sampler2D Texture_ScreenNormalMap;\n"
1088 "#ifdef USEDEFERREDLIGHTMAP\n"
1089 "uniform sampler2D Texture_ScreenDiffuse;\n"
1090 "uniform sampler2D Texture_ScreenSpecular;\n"
1093 "uniform myhalf3 Color_Pants;\n"
1094 "uniform myhalf3 Color_Shirt;\n"
1095 "uniform myhalf3 FogColor;\n"
1098 "uniform float FogRangeRecip;\n"
1099 "uniform float FogPlaneViewDist;\n"
1100 "uniform float FogHeightFade;\n"
1101 "vec3 FogVertex(vec3 surfacecolor)\n"
1103 " vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1104 " float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1106 "#ifdef USEFOGHEIGHTTEXTURE\n"
1107 " vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1108 " fogfrac = fogheightpixel.a;\n"
1109 " return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1111 "# ifdef USEFOGOUTSIDE\n"
1112 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1114 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1116 " return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1121 "#ifdef USEOFFSETMAPPING\n"
1122 "uniform float OffsetMapping_Scale;\n"
1123 "vec2 OffsetMapping(vec2 TexCoord)\n"
1125 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1126 " // 14 sample relief mapping: linear search and then binary search\n"
1127 " // this basically steps forward a small amount repeatedly until it finds\n"
1128 " // itself inside solid, then jitters forward and back using decreasing\n"
1129 " // amounts to find the impact\n"
1130 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1131 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1132 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1133 " vec3 RT = vec3(TexCoord, 1);\n"
1134 " OffsetVector *= 0.1;\n"
1135 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1136 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1138 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1139 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1143 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
1145 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
1146 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
1147 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
1148 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1151 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1152 " // this basically moves forward the full distance, and then backs up based\n"
1153 " // on height of samples\n"
1154 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1155 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1156 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1157 " TexCoord += OffsetVector;\n"
1158 " OffsetVector *= 0.333;\n"
1159 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1160 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1161 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1162 " return TexCoord;\n"
1165 "#endif // USEOFFSETMAPPING\n"
1167 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1168 "uniform sampler2D Texture_Attenuation;\n"
1169 "uniform samplerCube Texture_Cube;\n"
1172 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1174 "#ifdef USESHADOWMAP2D\n"
1175 "# ifdef USESHADOWSAMPLER\n"
1176 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1178 "uniform sampler2D Texture_ShadowMap2D;\n"
1182 "#ifdef USESHADOWMAPVSDCT\n"
1183 "uniform samplerCube Texture_CubeProjection;\n"
1186 "#if defined(USESHADOWMAP2D)\n"
1187 "uniform vec2 ShadowMap_TextureScale;\n"
1188 "uniform vec4 ShadowMap_Parameters;\n"
1191 "#if defined(USESHADOWMAP2D)\n"
1192 "# ifdef USESHADOWMAPORTHO\n"
1193 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1195 "# ifdef USESHADOWMAPVSDCT\n"
1196 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1198 " vec3 adir = abs(dir);\n"
1199 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1200 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1201 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1204 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 " vec3 adir = abs(dir);\n"
1207 " float ma = adir.z;\n"
1208 " vec4 proj = vec4(dir, 2.5);\n"
1209 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1210 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1211 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1212 " 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"
1216 "#endif // defined(USESHADOWMAP2D)\n"
1218 "# ifdef USESHADOWMAP2D\n"
1219 "float ShadowMapCompare(vec3 dir)\n"
1221 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1224 "# ifdef USESHADOWSAMPLER\n"
1225 "# ifdef USESHADOWMAPPCF\n"
1226 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1227 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1228 " 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"
1230 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1233 "# ifdef USESHADOWMAPPCF\n"
1234 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1235 "# ifdef GL_ARB_texture_gather\n"
1236 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1238 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1240 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1241 "# if USESHADOWMAPPCF > 1\n"
1242 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1243 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1244 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1245 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1246 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1247 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1248 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1249 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1250 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1251 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1252 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1253 " locols.yz += group2.ab;\n"
1254 " hicols.yz += group8.rg;\n"
1255 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1256 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1257 " mix(locols, hicols, offset.y);\n"
1258 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1259 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1260 " f = dot(cols, vec4(1.0/25.0));\n"
1262 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1263 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1264 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1265 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1266 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1267 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1268 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1271 "# ifdef GL_EXT_gpu_shader4\n"
1272 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1274 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1276 "# if USESHADOWMAPPCF > 1\n"
1277 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1278 " center *= ShadowMap_TextureScale;\n"
1279 " 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"
1280 " 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"
1281 " 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"
1282 " 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"
1283 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1284 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1286 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1287 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1288 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1289 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1290 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1291 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1295 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1298 "# ifdef USESHADOWMAPORTHO\n"
1299 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1305 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1306 "#endif // FRAGMENT_SHADER\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1312 "#ifdef VERTEX_SHADER\n"
1313 "uniform mat4 TexMatrix;\n"
1314 "#ifdef USEVERTEXTEXTUREBLEND\n"
1315 "uniform mat4 BackgroundTexMatrix;\n"
1317 "uniform mat4 ModelViewMatrix;\n"
1320 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1321 "#ifdef USEVERTEXTEXTUREBLEND\n"
1322 " gl_FrontColor = gl_Color;\n"
1323 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1326 " // transform unnormalized eye direction into tangent space\n"
1327 "#ifdef USEOFFSETMAPPING\n"
1328 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1329 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1330 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1331 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1334 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1335 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1336 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1337 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1339 "#endif // VERTEX_SHADER\n"
1341 "#ifdef FRAGMENT_SHADER\n"
1344 "#ifdef USEOFFSETMAPPING\n"
1345 " // apply offsetmapping\n"
1346 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1347 "#define TexCoord TexCoordOffset\n"
1350 "#ifdef USEALPHAKILL\n"
1351 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1355 "#ifdef USEVERTEXTEXTUREBLEND\n"
1356 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1357 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1358 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1359 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1362 "#ifdef USEVERTEXTEXTUREBLEND\n"
1363 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1364 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1366 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1367 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1370 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1372 "#endif // FRAGMENT_SHADER\n"
1373 "#else // !MODE_DEFERREDGEOMETRY\n"
1378 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1379 "#ifdef VERTEX_SHADER\n"
1380 "uniform mat4 ModelViewMatrix;\n"
1383 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1384 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1386 "#endif // VERTEX_SHADER\n"
1388 "#ifdef FRAGMENT_SHADER\n"
1389 "uniform mat4 ViewToLight;\n"
1390 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1391 "uniform vec2 ScreenToDepth;\n"
1392 "uniform myhalf3 DeferredColor_Ambient;\n"
1393 "uniform myhalf3 DeferredColor_Diffuse;\n"
1394 "#ifdef USESPECULAR\n"
1395 "uniform myhalf3 DeferredColor_Specular;\n"
1396 "uniform myhalf SpecularPower;\n"
1398 "uniform myhalf2 PixelToScreenTexCoord;\n"
1401 " // calculate viewspace pixel position\n"
1402 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1404 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1405 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1406 " // decode viewspace pixel normal\n"
1407 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1408 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1409 " // surfacenormal = pixel normal in viewspace\n"
1410 " // LightVector = pixel to light in viewspace\n"
1411 " // CubeVector = position in lightspace\n"
1412 " // eyevector = pixel to view in viewspace\n"
1413 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1414 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1415 "#ifdef USEDIFFUSE\n"
1416 " // calculate diffuse shading\n"
1417 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1418 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1420 "#ifdef USESPECULAR\n"
1421 " // calculate directional shading\n"
1422 " vec3 eyevector = position * -1.0;\n"
1423 "# ifdef USEEXACTSPECULARMATH\n"
1424 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1426 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1427 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1431 "#if defined(USESHADOWMAP2D)\n"
1432 " fade *= ShadowMapCompare(CubeVector);\n"
1435 "#ifdef USEDIFFUSE\n"
1436 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1438 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1440 "#ifdef USESPECULAR\n"
1441 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1443 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1446 "# ifdef USECUBEFILTER\n"
1447 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1448 " gl_FragData[0].rgb *= cubecolor;\n"
1449 " gl_FragData[1].rgb *= cubecolor;\n"
1452 "#endif // FRAGMENT_SHADER\n"
1453 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1458 "#ifdef VERTEX_SHADER\n"
1459 "uniform mat4 TexMatrix;\n"
1460 "#ifdef USEVERTEXTEXTUREBLEND\n"
1461 "uniform mat4 BackgroundTexMatrix;\n"
1463 "#ifdef MODE_LIGHTSOURCE\n"
1464 "uniform mat4 ModelToLight;\n"
1466 "#ifdef USESHADOWMAPORTHO\n"
1467 "uniform mat4 ShadowMapMatrix;\n"
1471 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1472 " gl_FrontColor = gl_Color;\n"
1474 " // copy the surface texcoord\n"
1475 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1476 "#ifdef USEVERTEXTEXTUREBLEND\n"
1477 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1479 "#ifdef USELIGHTMAP\n"
1480 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1483 "#ifdef MODE_LIGHTSOURCE\n"
1484 " // transform vertex position into light attenuation/cubemap space\n"
1485 " // (-1 to +1 across the light box)\n"
1486 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1488 "# ifdef USEDIFFUSE\n"
1489 " // transform unnormalized light direction into tangent space\n"
1490 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1491 " // normalize it per pixel)\n"
1492 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1493 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1494 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1495 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1499 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1500 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1501 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1502 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1505 " // transform unnormalized eye direction into tangent space\n"
1506 "#ifdef USEEYEVECTOR\n"
1507 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1508 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1509 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1510 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1514 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1515 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1518 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1519 " VectorS = gl_MultiTexCoord1.xyz;\n"
1520 " VectorT = gl_MultiTexCoord2.xyz;\n"
1521 " VectorR = gl_MultiTexCoord3.xyz;\n"
1524 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1525 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1527 "#ifdef USESHADOWMAPORTHO\n"
1528 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1531 "#ifdef USEREFLECTION\n"
1532 " ModelViewProjectionPosition = gl_Position;\n"
1535 "#endif // VERTEX_SHADER\n"
1540 "#ifdef FRAGMENT_SHADER\n"
1541 "#ifdef USEDEFERREDLIGHTMAP\n"
1542 "uniform myhalf2 PixelToScreenTexCoord;\n"
1543 "uniform myhalf3 DeferredMod_Diffuse;\n"
1544 "uniform myhalf3 DeferredMod_Specular;\n"
1546 "uniform myhalf3 Color_Ambient;\n"
1547 "uniform myhalf3 Color_Diffuse;\n"
1548 "uniform myhalf3 Color_Specular;\n"
1549 "uniform myhalf SpecularPower;\n"
1551 "uniform myhalf3 Color_Glow;\n"
1553 "uniform myhalf Alpha;\n"
1554 "#ifdef USEREFLECTION\n"
1555 "uniform vec4 DistortScaleRefractReflect;\n"
1556 "uniform vec4 ScreenScaleRefractReflect;\n"
1557 "uniform vec4 ScreenCenterRefractReflect;\n"
1558 "uniform myhalf4 ReflectColor;\n"
1560 "#ifdef USEREFLECTCUBE\n"
1561 "uniform mat4 ModelToReflectCube;\n"
1562 "uniform sampler2D Texture_ReflectMask;\n"
1563 "uniform samplerCube Texture_ReflectCube;\n"
1565 "#ifdef MODE_LIGHTDIRECTION\n"
1566 "uniform myhalf3 LightColor;\n"
1568 "#ifdef MODE_LIGHTSOURCE\n"
1569 "uniform myhalf3 LightColor;\n"
1573 "#ifdef USEOFFSETMAPPING\n"
1574 " // apply offsetmapping\n"
1575 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1576 "#define TexCoord TexCoordOffset\n"
1579 " // combine the diffuse textures (base, pants, shirt)\n"
1580 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1581 "#ifdef USEALPHAKILL\n"
1582 " if (color.a < 0.5)\n"
1585 " color.a *= Alpha;\n"
1586 "#ifdef USECOLORMAPPING\n"
1587 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1589 "#ifdef USEVERTEXTEXTUREBLEND\n"
1590 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1591 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1592 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1593 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1595 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1598 " // get the surface normal\n"
1599 "#ifdef USEVERTEXTEXTUREBLEND\n"
1600 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1602 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1605 " // get the material colors\n"
1606 " myhalf3 diffusetex = color.rgb;\n"
1607 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1608 "# ifdef USEVERTEXTEXTUREBLEND\n"
1609 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1611 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1615 "#ifdef USEREFLECTCUBE\n"
1616 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1617 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1618 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1619 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1625 "#ifdef MODE_LIGHTSOURCE\n"
1626 " // light source\n"
1627 "#ifdef USEDIFFUSE\n"
1628 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1629 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1630 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1631 "#ifdef USESPECULAR\n"
1632 "#ifdef USEEXACTSPECULARMATH\n"
1633 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1635 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1636 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1638 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1641 " color.rgb = diffusetex * Color_Ambient;\n"
1643 " color.rgb *= LightColor;\n"
1644 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1645 "#if defined(USESHADOWMAP2D)\n"
1646 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1648 "# ifdef USECUBEFILTER\n"
1649 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1651 "#endif // MODE_LIGHTSOURCE\n"
1656 "#ifdef MODE_LIGHTDIRECTION\n"
1658 "#ifdef USEDIFFUSE\n"
1659 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1661 "#define lightcolor LightColor\n"
1662 "#endif // MODE_LIGHTDIRECTION\n"
1663 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1665 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1666 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1667 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1668 " // convert modelspace light vector to tangentspace\n"
1669 " myhalf3 lightnormal;\n"
1670 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1671 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1672 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1673 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1674 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1675 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1676 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1677 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1678 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1679 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1680 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1681 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1682 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1683 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1684 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1686 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1687 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1688 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1694 "#ifdef MODE_FAKELIGHT\n"
1696 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1697 "myhalf3 lightcolor = myhalf3(1.0);\n"
1698 "#endif // MODE_FAKELIGHT\n"
1703 "#ifdef MODE_LIGHTMAP\n"
1704 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1705 "#endif // MODE_LIGHTMAP\n"
1706 "#ifdef MODE_VERTEXCOLOR\n"
1707 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1708 "#endif // MODE_VERTEXCOLOR\n"
1709 "#ifdef MODE_FLATCOLOR\n"
1710 " color.rgb = diffusetex * Color_Ambient;\n"
1711 "#endif // MODE_FLATCOLOR\n"
1717 "# ifdef USEDIFFUSE\n"
1718 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1719 "# ifdef USESPECULAR\n"
1720 "# ifdef USEEXACTSPECULARMATH\n"
1721 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1723 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1724 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1726 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1728 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1731 " color.rgb = diffusetex * Color_Ambient;\n"
1735 "#ifdef USESHADOWMAPORTHO\n"
1736 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1739 "#ifdef USEDEFERREDLIGHTMAP\n"
1740 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1741 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1742 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1746 "#ifdef USEVERTEXTEXTUREBLEND\n"
1747 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1749 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1754 " color.rgb = FogVertex(color.rgb);\n"
1757 " // 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"
1758 "#ifdef USEREFLECTION\n"
1759 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1760 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1761 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1762 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1763 " // FIXME temporary hack to detect the case that the reflection\n"
1764 " // gets blackened at edges due to leaving the area that contains actual\n"
1766 " // Remove this 'ack once we have a better way to stop this thing from\n"
1768 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1769 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1770 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1771 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1772 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1773 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1776 " gl_FragColor = vec4(color);\n"
1778 "#endif // FRAGMENT_SHADER\n"
1780 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1781 "#endif // !MODE_DEFERREDGEOMETRY\n"
1782 "#endif // !MODE_WATER\n"
1783 "#endif // !MODE_REFRACTION\n"
1784 "#endif // !MODE_BLOOMBLUR\n"
1785 "#endif // !MODE_GENERIC\n"
1786 "#endif // !MODE_POSTPROCESS\n"
1787 "#endif // !MODE_SHOWDEPTH\n"
1788 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1792 =========================================================================================================================================================
1796 =========================================================================================================================================================
1800 =========================================================================================================================================================
1804 =========================================================================================================================================================
1808 =========================================================================================================================================================
1812 =========================================================================================================================================================
1816 =========================================================================================================================================================
1819 const char *builtincgshaderstring =
1820 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1821 "// written by Forest 'LordHavoc' Hale\n"
1822 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1824 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1825 "#if defined(USEREFLECTION)\n"
1826 "#undef USESHADOWMAPORTHO\n"
1829 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1832 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1833 "#define USELIGHTMAP\n"
1835 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1836 "#define USEEYEVECTOR\n"
1839 "#ifdef FRAGMENT_SHADER\n"
1841 "//#undef USESHADOWMAPPCF\n"
1842 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1843 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1845 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1849 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1850 "#ifdef VERTEX_SHADER\n"
1853 "float4 gl_Vertex : POSITION,\n"
1854 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1855 "out float4 gl_Position : POSITION,\n"
1856 "out float Depth : TEXCOORD0\n"
1859 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1860 " Depth = gl_Position.z;\n"
1864 "#ifdef FRAGMENT_SHADER\n"
1867 "float Depth : TEXCOORD0,\n"
1868 "out float4 gl_FragColor : COLOR\n"
1871 "// float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1872 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1873 " temp.yz -= floor(temp.yz);\n"
1874 " gl_FragColor = temp;\n"
1875 "// gl_FragColor = float4(Depth,0,0,0);\n"
1878 "#else // !MODE_DEPTH_ORSHADOW\n"
1883 "#ifdef MODE_SHOWDEPTH\n"
1884 "#ifdef VERTEX_SHADER\n"
1887 "float4 gl_Vertex : POSITION,\n"
1888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1889 "out float4 gl_Position : POSITION,\n"
1890 "out float4 gl_FrontColor : COLOR0\n"
1893 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1894 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1901 "float4 gl_FrontColor : COLOR0,\n"
1902 "out float4 gl_FragColor : COLOR\n"
1905 " gl_FragColor = gl_FrontColor;\n"
1908 "#else // !MODE_SHOWDEPTH\n"
1913 "#ifdef MODE_POSTPROCESS\n"
1915 "#ifdef VERTEX_SHADER\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1922 "out float4 gl_Position : POSITION,\n"
1923 "out float2 TexCoord1 : TEXCOORD0,\n"
1924 "out float2 TexCoord2 : TEXCOORD1\n"
1927 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1928 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1930 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1935 "#ifdef FRAGMENT_SHADER\n"
1938 "float2 TexCoord1 : TEXCOORD0,\n"
1939 "float2 TexCoord2 : TEXCOORD1,\n"
1940 "uniform sampler Texture_First : register(s0),\n"
1942 "uniform sampler Texture_Second : register(s1),\n"
1944 "#ifdef USEGAMMARAMPS\n"
1945 "uniform sampler Texture_GammaRamps : register(s2),\n"
1947 "#ifdef USESATURATION\n"
1948 "uniform float Saturation : register(c30),\n"
1950 "#ifdef USEVIEWTINT\n"
1951 "uniform float4 ViewTintColor : register(c41),\n"
1953 "uniform float4 UserVec1 : register(c37),\n"
1954 "uniform float4 UserVec2 : register(c38),\n"
1955 "uniform float4 UserVec3 : register(c39),\n"
1956 "uniform float4 UserVec4 : register(c40),\n"
1957 "uniform float ClientTime : register(c2),\n"
1958 "uniform float2 PixelSize : register(c25),\n"
1959 "uniform float4 BloomColorSubtract : register(c43),\n"
1960 "out float4 gl_FragColor : COLOR\n"
1963 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1965 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1967 "#ifdef USEVIEWTINT\n"
1968 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1971 "#ifdef USEPOSTPROCESSING\n"
1972 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1973 "// 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"
1974 " float sobel = 1.0;\n"
1975 " // float2 ts = textureSize(Texture_First, 0);\n"
1976 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1977 " float2 px = PixelSize;\n"
1978 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1979 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1980 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1981 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1982 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1983 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1984 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1985 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1986 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1987 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1988 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1989 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1990 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1991 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1992 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1993 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1994 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1995 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1996 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1997 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1998 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1999 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2000 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2001 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2002 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2003 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2004 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2005 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2006 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2007 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2008 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2009 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2012 "#ifdef USESATURATION\n"
2013 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2014 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2015 " // 'vampire sight' effect, wheres red is compensated\n"
2016 " #ifdef SATURATION_REDCOMPENSATE\n"
2017 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2018 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2019 " gl_FragColor.r += r;\n"
2021 " // normal desaturation\n"
2022 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2023 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2027 "#ifdef USEGAMMARAMPS\n"
2028 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2029 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2030 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2034 "#else // !MODE_POSTPROCESS\n"
2039 "#ifdef MODE_GENERIC\n"
2040 "#ifdef VERTEX_SHADER\n"
2043 "float4 gl_Vertex : POSITION,\n"
2044 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2045 "float4 gl_Color : COLOR0,\n"
2046 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2047 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2048 "out float4 gl_Position : POSITION,\n"
2049 "#ifdef USEDIFFUSE\n"
2050 "out float2 TexCoord1 : TEXCOORD0,\n"
2052 "#ifdef USESPECULAR\n"
2053 "out float2 TexCoord2 : TEXCOORD1,\n"
2055 "out float4 gl_FrontColor : COLOR\n"
2059 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2061 " gl_FrontColor = gl_Color; // Cg is forward\n"
2063 "#ifdef USEDIFFUSE\n"
2064 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2066 "#ifdef USESPECULAR\n"
2067 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2069 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2073 "#ifdef FRAGMENT_SHADER\n"
2077 "float4 gl_FrontColor : COLOR0,\n"
2078 "float2 TexCoord1 : TEXCOORD0,\n"
2079 "float2 TexCoord2 : TEXCOORD1,\n"
2080 "#ifdef USEDIFFUSE\n"
2081 "uniform sampler Texture_First : register(s0),\n"
2083 "#ifdef USESPECULAR\n"
2084 "uniform sampler Texture_Second : register(s1),\n"
2086 "out float4 gl_FragColor : COLOR\n"
2089 " gl_FragColor = gl_FrontColor;\n"
2090 "#ifdef USEDIFFUSE\n"
2091 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2094 "#ifdef USESPECULAR\n"
2095 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2096 "# ifdef USECOLORMAPPING\n"
2097 " gl_FragColor *= tex2;\n"
2100 " gl_FragColor += tex2;\n"
2102 "# ifdef USEVERTEXTEXTUREBLEND\n"
2103 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2108 "#else // !MODE_GENERIC\n"
2113 "#ifdef MODE_BLOOMBLUR\n"
2114 "#ifdef VERTEX_SHADER\n"
2117 "float4 gl_Vertex : POSITION,\n"
2118 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2119 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2120 "out float4 gl_Position : POSITION,\n"
2121 "out float2 TexCoord : TEXCOORD0\n"
2124 " TexCoord = gl_MultiTexCoord0.xy;\n"
2125 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2129 "#ifdef FRAGMENT_SHADER\n"
2133 "float2 TexCoord : TEXCOORD0,\n"
2134 "uniform sampler Texture_First : register(s0),\n"
2135 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2136 "out float4 gl_FragColor : COLOR\n"
2140 " float2 tc = TexCoord;\n"
2141 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2142 " tc += BloomBlur_Parameters.xy;\n"
2143 " for (i = 1;i < SAMPLES;i++)\n"
2145 " color += tex2D(Texture_First, tc).rgb;\n"
2146 " tc += BloomBlur_Parameters.xy;\n"
2148 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2151 "#else // !MODE_BLOOMBLUR\n"
2152 "#ifdef MODE_REFRACTION\n"
2153 "#ifdef VERTEX_SHADER\n"
2156 "float4 gl_Vertex : POSITION,\n"
2157 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2158 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2159 "uniform float4x4 TexMatrix : register(c0),\n"
2160 "uniform float3 EyePosition : register(c24),\n"
2161 "out float4 gl_Position : POSITION,\n"
2162 "out float2 TexCoord : TEXCOORD0,\n"
2163 "out float3 EyeVector : TEXCOORD1,\n"
2164 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2167 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2168 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2169 " ModelViewProjectionPosition = gl_Position;\n"
2173 "#ifdef FRAGMENT_SHADER\n"
2176 "float2 TexCoord : TEXCOORD0,\n"
2177 "float3 EyeVector : TEXCOORD1,\n"
2178 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2179 "uniform sampler Texture_Normal : register(s0),\n"
2180 "uniform sampler Texture_Refraction : register(s3),\n"
2181 "uniform sampler Texture_Reflection : register(s7),\n"
2182 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2183 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2184 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2185 "uniform float4 RefractColor : register(c29),\n"
2186 "out float4 gl_FragColor : COLOR\n"
2189 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2190 " //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"
2191 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2192 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2193 " // FIXME temporary hack to detect the case that the reflection\n"
2194 " // gets blackened at edges due to leaving the area that contains actual\n"
2196 " // Remove this 'ack once we have a better way to stop this thing from\n"
2198 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2199 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2200 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2201 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2202 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2203 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2206 "#else // !MODE_REFRACTION\n"
2211 "#ifdef MODE_WATER\n"
2212 "#ifdef VERTEX_SHADER\n"
2216 "float4 gl_Vertex : POSITION,\n"
2217 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2218 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2219 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2220 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2221 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2222 "uniform float4x4 TexMatrix : register(c0),\n"
2223 "uniform float3 EyePosition : register(c24),\n"
2224 "out float4 gl_Position : POSITION,\n"
2225 "out float2 TexCoord : TEXCOORD0,\n"
2226 "out float3 EyeVector : TEXCOORD1,\n"
2227 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2230 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2231 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2232 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2233 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2234 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2235 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2236 " ModelViewProjectionPosition = gl_Position;\n"
2240 "#ifdef FRAGMENT_SHADER\n"
2243 "float2 TexCoord : TEXCOORD0,\n"
2244 "float3 EyeVector : TEXCOORD1,\n"
2245 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2246 "uniform sampler Texture_Normal : register(s0),\n"
2247 "uniform sampler Texture_Refraction : register(s3),\n"
2248 "uniform sampler Texture_Reflection : register(s7),\n"
2249 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2250 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2251 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2252 "uniform float4 RefractColor : register(c29),\n"
2253 "uniform float4 ReflectColor : register(c26),\n"
2254 "uniform float ReflectFactor : register(c27),\n"
2255 "uniform float ReflectOffset : register(c28),\n"
2256 "out float4 gl_FragColor : COLOR\n"
2259 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2260 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2261 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2262 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2263 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2264 " // FIXME temporary hack to detect the case that the reflection\n"
2265 " // gets blackened at edges due to leaving the area that contains actual\n"
2267 " // Remove this 'ack once we have a better way to stop this thing from\n"
2269 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2270 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2271 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2272 " f *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2273 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2274 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2275 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2276 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2277 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2278 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2279 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2280 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2283 "#else // !MODE_WATER\n"
2288 "// 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"
2290 "// fragment shader specific:\n"
2291 "#ifdef FRAGMENT_SHADER\n"
2294 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2297 "#ifdef USEFOGHEIGHTTEXTURE\n"
2298 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2299 " fogfrac = fogheightpixel.a;\n"
2300 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2302 "# ifdef USEFOGOUTSIDE\n"
2303 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2305 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2307 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2312 "#ifdef USEOFFSETMAPPING\n"
2313 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2315 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2316 " // 14 sample relief mapping: linear search and then binary search\n"
2317 " // this basically steps forward a small amount repeatedly until it finds\n"
2318 " // itself inside solid, then jitters forward and back using decreasing\n"
2319 " // amounts to find the impact\n"
2320 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2321 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2322 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2323 " float3 RT = float3(TexCoord, 1);\n"
2324 " OffsetVector *= 0.1;\n"
2325 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2326 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2327 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2328 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2333 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2334 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
2335 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2336 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2337 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2338 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2341 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2342 " // this basically moves forward the full distance, and then backs up based\n"
2343 " // on height of samples\n"
2344 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2345 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2346 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2347 " TexCoord += OffsetVector;\n"
2348 " OffsetVector *= 0.333;\n"
2349 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2350 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2351 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2352 " return TexCoord;\n"
2355 "#endif // USEOFFSETMAPPING\n"
2357 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2358 "#if defined(USESHADOWMAP2D)\n"
2359 "# ifdef USESHADOWMAPORTHO\n"
2360 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2362 "# ifdef USESHADOWMAPVSDCT\n"
2363 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2365 " float3 adir = abs(dir);\n"
2366 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2367 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2368 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2371 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2373 " float3 adir = abs(dir);\n"
2374 " float ma = adir.z;\n"
2375 " float4 proj = float4(dir, 2.5);\n"
2376 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2377 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2379 " 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"
2381 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2382 " 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"
2387 "#endif // defined(USESHADOWMAP2D)\n"
2389 "# ifdef USESHADOWMAP2D\n"
2390 "#ifdef USESHADOWMAPVSDCT\n"
2391 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2393 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2396 "#ifdef USESHADOWMAPVSDCT\n"
2397 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2399 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2403 "# ifdef USESHADOWSAMPLER\n"
2404 "# ifdef USESHADOWMAPPCF\n"
2405 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2406 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2407 " 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"
2409 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2412 "# ifdef USESHADOWMAPPCF\n"
2413 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2414 "# ifdef GL_ARB_texture_gather\n"
2415 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2417 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2419 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2420 "# if USESHADOWMAPPCF > 1\n"
2421 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2422 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2423 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2424 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2425 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2426 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2427 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2428 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2429 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2430 " float4 locols = float4(group1.ab, group3.ab);\n"
2431 " float4 hicols = float4(group7.rg, group9.rg);\n"
2432 " locols.yz += group2.ab;\n"
2433 " hicols.yz += group8.rg;\n"
2434 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2435 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2436 " lerp(locols, hicols, offset.y);\n"
2437 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2438 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2439 " f = dot(cols, float4(1.0/25.0));\n"
2441 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2442 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2443 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2444 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2445 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2446 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2447 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2450 "# ifdef GL_EXT_gpu_shader4\n"
2451 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2453 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2455 "# if USESHADOWMAPPCF > 1\n"
2456 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2457 " center *= ShadowMap_TextureScale;\n"
2458 " 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"
2459 " 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"
2460 " 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"
2461 " 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"
2462 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2463 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2465 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2466 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2467 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2468 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2469 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2470 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2474 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2477 "# ifdef USESHADOWMAPORTHO\n"
2478 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2484 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2485 "#endif // FRAGMENT_SHADER\n"
2490 "#ifdef MODE_DEFERREDGEOMETRY\n"
2491 "#ifdef VERTEX_SHADER\n"
2494 "float4 gl_Vertex : POSITION,\n"
2495 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2496 "#ifdef USEVERTEXTEXTUREBLEND\n"
2497 "float4 gl_Color : COLOR0,\n"
2499 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2500 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2501 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2502 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2503 "uniform float4x4 TexMatrix : register(c0),\n"
2504 "#ifdef USEVERTEXTEXTUREBLEND\n"
2505 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2507 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2508 "#ifdef USEOFFSETMAPPING\n"
2509 "uniform float3 EyePosition : register(c24),\n"
2511 "out float4 gl_Position : POSITION,\n"
2512 "#ifdef USEVERTEXTEXTUREBLEND\n"
2513 "out float4 gl_FrontColor : COLOR,\n"
2515 "out float4 TexCoordBoth : TEXCOORD0,\n"
2516 "#ifdef USEOFFSETMAPPING\n"
2517 "out float3 EyeVector : TEXCOORD2,\n"
2519 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2520 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2521 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2524 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2529 " gl_FrontColor = gl_Color; // Cg is forward\n"
2531 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2534 " // transform unnormalized eye direction into tangent space\n"
2535 "#ifdef USEOFFSETMAPPING\n"
2536 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2537 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2538 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2539 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2542 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2543 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2544 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2545 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2546 " VectorR.w = gl_Position.z;\n"
2548 "#endif // VERTEX_SHADER\n"
2550 "#ifdef FRAGMENT_SHADER\n"
2553 "float4 TexCoordBoth : TEXCOORD0,\n"
2554 "float3 EyeVector : TEXCOORD2,\n"
2555 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2556 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2557 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2558 "uniform sampler Texture_Normal : register(s0),\n"
2559 "#ifdef USEALPHAKILL\n"
2560 "uniform sampler Texture_Color : register(s1),\n"
2562 "uniform sampler Texture_Gloss : register(s2),\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2564 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2565 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "uniform float OffsetMapping_Scale : register(c24),\n"
2570 "uniform half SpecularPower : register(c36),\n"
2572 "out float4 gl_FragData0 : COLOR0,\n"
2573 "out float4 gl_FragData1 : COLOR1\n"
2575 "out float4 gl_FragColor : COLOR\n"
2579 " float2 TexCoord = TexCoordBoth.xy;\n"
2580 "#ifdef USEOFFSETMAPPING\n"
2581 " // apply offsetmapping\n"
2582 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2583 "#define TexCoord TexCoordOffset\n"
2586 "#ifdef USEALPHAKILL\n"
2587 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2591 "#ifdef USEVERTEXTEXTUREBLEND\n"
2592 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2593 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2594 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2595 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2598 "#ifdef USEVERTEXTEXTUREBLEND\n"
2599 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2600 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2602 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2603 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2607 " gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2608 " float Depth = VectorR.w / 256.0;\n"
2609 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2610 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2611 " depthcolor.yz -= floor(depthcolor.yz);\n"
2612 " gl_FragData1 = depthcolor;\n"
2614 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2617 "#endif // FRAGMENT_SHADER\n"
2618 "#else // !MODE_DEFERREDGEOMETRY\n"
2623 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2624 "#ifdef VERTEX_SHADER\n"
2627 "float4 gl_Vertex : POSITION,\n"
2628 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2629 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2630 "out float4 gl_Position : POSITION,\n"
2631 "out float4 ModelViewPosition : TEXCOORD0\n"
2634 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2635 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2637 "#endif // VERTEX_SHADER\n"
2639 "#ifdef FRAGMENT_SHADER\n"
2643 "float2 Pixel : VPOS,\n"
2645 "float2 Pixel : WPOS,\n"
2647 "float4 ModelViewPosition : TEXCOORD0,\n"
2648 "uniform float4x4 ViewToLight : register(c44),\n"
2649 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2650 "uniform float3 LightPosition : register(c23),\n"
2651 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2652 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2653 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2654 "#ifdef USESPECULAR\n"
2655 "uniform half3 DeferredColor_Specular : register(c11),\n"
2656 "uniform half SpecularPower : register(c36),\n"
2658 "uniform sampler Texture_Attenuation : register(s9),\n"
2659 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2660 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2662 "#ifdef USECUBEFILTER\n"
2663 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2666 "#ifdef USESHADOWMAP2D\n"
2667 "# ifdef USESHADOWSAMPLER\n"
2668 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2670 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2674 "#ifdef USESHADOWMAPVSDCT\n"
2675 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2678 "#if defined(USESHADOWMAP2D)\n"
2679 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2680 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2683 "out float4 gl_FragData0 : COLOR0,\n"
2684 "out float4 gl_FragData1 : COLOR1\n"
2687 " // calculate viewspace pixel position\n"
2688 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2689 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2690 " float3 position;\n"
2692 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2694 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2696 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2697 " // decode viewspace pixel normal\n"
2698 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2699 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2700 " // surfacenormal = pixel normal in viewspace\n"
2701 " // LightVector = pixel to light in viewspace\n"
2702 " // CubeVector = position in lightspace\n"
2703 " // eyevector = pixel to view in viewspace\n"
2704 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2705 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2706 "#ifdef USEDIFFUSE\n"
2707 " // calculate diffuse shading\n"
2708 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2709 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2711 "#ifdef USESPECULAR\n"
2712 " // calculate directional shading\n"
2713 " float3 eyevector = position * -1.0;\n"
2714 "# ifdef USEEXACTSPECULARMATH\n"
2715 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2717 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2718 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2722 "#if defined(USESHADOWMAP2D)\n"
2723 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2724 "#ifdef USESHADOWMAPVSDCT\n"
2725 ", Texture_CubeProjection\n"
2730 "#ifdef USEDIFFUSE\n"
2731 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2733 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2735 "#ifdef USESPECULAR\n"
2736 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2738 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2741 "# ifdef USECUBEFILTER\n"
2742 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2743 " gl_FragData0.rgb *= cubecolor;\n"
2744 " gl_FragData1.rgb *= cubecolor;\n"
2747 "#endif // FRAGMENT_SHADER\n"
2748 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2753 "#ifdef VERTEX_SHADER\n"
2756 "float4 gl_Vertex : POSITION,\n"
2757 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2758 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2759 "float4 gl_Color : COLOR0,\n"
2761 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2762 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2763 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2764 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2765 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2767 "uniform float3 EyePosition : register(c24),\n"
2768 "uniform float4x4 TexMatrix : register(c0),\n"
2769 "#ifdef USEVERTEXTEXTUREBLEND\n"
2770 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2772 "#ifdef MODE_LIGHTSOURCE\n"
2773 "uniform float4x4 ModelToLight : register(c20),\n"
2775 "#ifdef MODE_LIGHTSOURCE\n"
2776 "uniform float3 LightPosition : register(c27),\n"
2778 "#ifdef MODE_LIGHTDIRECTION\n"
2779 "uniform float3 LightDir : register(c26),\n"
2781 "uniform float4 FogPlane : register(c25),\n"
2782 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2783 "uniform float3 LightPosition : register(c27),\n"
2785 "#ifdef USESHADOWMAPORTHO\n"
2786 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2788 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2789 "out float4 gl_FrontColor : COLOR,\n"
2791 "out float4 TexCoordBoth : TEXCOORD0,\n"
2792 "#ifdef USELIGHTMAP\n"
2793 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2795 "#ifdef USEEYEVECTOR\n"
2796 "out float3 EyeVector : TEXCOORD2,\n"
2798 "#ifdef USEREFLECTION\n"
2799 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2802 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2804 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2805 "out float3 LightVector : TEXCOORD1,\n"
2807 "#ifdef MODE_LIGHTSOURCE\n"
2808 "out float3 CubeVector : TEXCOORD3,\n"
2810 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2811 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2812 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2813 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2815 "#ifdef USESHADOWMAPORTHO\n"
2816 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2818 "out float4 gl_Position : POSITION\n"
2821 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2823 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2825 " gl_FrontColor = gl_Color; // Cg is forward\n"
2828 " // copy the surface texcoord\n"
2829 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2830 "#ifdef USEVERTEXTEXTUREBLEND\n"
2831 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2833 "#ifdef USELIGHTMAP\n"
2834 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2837 "#ifdef MODE_LIGHTSOURCE\n"
2838 " // transform vertex position into light attenuation/cubemap space\n"
2839 " // (-1 to +1 across the light box)\n"
2840 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2842 "# ifdef USEDIFFUSE\n"
2843 " // transform unnormalized light direction into tangent space\n"
2844 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2845 " // normalize it per pixel)\n"
2846 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2847 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2848 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2849 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2853 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2854 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2855 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2856 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2859 " // transform unnormalized eye direction into tangent space\n"
2860 "#ifdef USEEYEVECTOR\n"
2861 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2862 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2863 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2864 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2868 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2869 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2872 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2873 " VectorS = gl_MultiTexCoord1.xyz;\n"
2874 " VectorT = gl_MultiTexCoord2.xyz;\n"
2875 " VectorR = gl_MultiTexCoord3.xyz;\n"
2878 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2879 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2881 "#ifdef USESHADOWMAPORTHO\n"
2882 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2885 "#ifdef USEREFLECTION\n"
2886 " ModelViewProjectionPosition = gl_Position;\n"
2889 "#endif // VERTEX_SHADER\n"
2894 "#ifdef FRAGMENT_SHADER\n"
2897 "#ifdef USEDEFERREDLIGHTMAP\n"
2899 "float2 Pixel : VPOS,\n"
2901 "float2 Pixel : WPOS,\n"
2904 "float4 gl_FrontColor : COLOR,\n"
2905 "float4 TexCoordBoth : TEXCOORD0,\n"
2906 "#ifdef USELIGHTMAP\n"
2907 "float2 TexCoordLightmap : TEXCOORD1,\n"
2909 "#ifdef USEEYEVECTOR\n"
2910 "float3 EyeVector : TEXCOORD2,\n"
2912 "#ifdef USEREFLECTION\n"
2913 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2916 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2918 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2919 "float3 LightVector : TEXCOORD1,\n"
2921 "#ifdef MODE_LIGHTSOURCE\n"
2922 "float3 CubeVector : TEXCOORD3,\n"
2924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2925 "float4 ModelViewPosition : TEXCOORD0,\n"
2927 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2928 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2929 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2930 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2932 "#ifdef USESHADOWMAPORTHO\n"
2933 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2936 "uniform sampler Texture_Normal : register(s0),\n"
2937 "uniform sampler Texture_Color : register(s1),\n"
2938 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2939 "uniform sampler Texture_Gloss : register(s2),\n"
2942 "uniform sampler Texture_Glow : register(s3),\n"
2944 "#ifdef USEVERTEXTEXTUREBLEND\n"
2945 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2946 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2947 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2948 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2951 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2954 "#ifdef USECOLORMAPPING\n"
2955 "uniform sampler Texture_Pants : register(s4),\n"
2956 "uniform sampler Texture_Shirt : register(s7),\n"
2959 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2960 "uniform sampler Texture_FogMask : register(s8),\n"
2962 "#ifdef USELIGHTMAP\n"
2963 "uniform sampler Texture_Lightmap : register(s9),\n"
2965 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2966 "uniform sampler Texture_Deluxemap : register(s10),\n"
2968 "#ifdef USEREFLECTION\n"
2969 "uniform sampler Texture_Reflection : register(s7),\n"
2972 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2973 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2974 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2976 "#ifdef USEDEFERREDLIGHTMAP\n"
2977 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2978 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2979 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2980 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2983 "#ifdef USECOLORMAPPING\n"
2984 "uniform half3 Color_Pants : register(c7),\n"
2985 "uniform half3 Color_Shirt : register(c8),\n"
2988 "uniform float3 FogColor : register(c16),\n"
2989 "uniform float FogRangeRecip : register(c20),\n"
2990 "uniform float FogPlaneViewDist : register(c19),\n"
2991 "uniform float FogHeightFade : register(c17),\n"
2994 "#ifdef USEOFFSETMAPPING\n"
2995 "uniform float OffsetMapping_Scale : register(c24),\n"
2998 "#ifdef USEDEFERREDLIGHTMAP\n"
2999 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3000 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3001 "uniform half3 DeferredMod_Specular : register(c13),\n"
3003 "uniform half3 Color_Ambient : register(c3),\n"
3004 "uniform half3 Color_Diffuse : register(c4),\n"
3005 "uniform half3 Color_Specular : register(c5),\n"
3006 "uniform half SpecularPower : register(c36),\n"
3008 "uniform half3 Color_Glow : register(c6),\n"
3010 "uniform half Alpha : register(c0),\n"
3011 "#ifdef USEREFLECTION\n"
3012 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3013 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3014 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3015 "uniform half4 ReflectColor : register(c26),\n"
3017 "#ifdef USEREFLECTCUBE\n"
3018 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3019 "uniform sampler Texture_ReflectMask : register(s5),\n"
3020 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3022 "#ifdef MODE_LIGHTDIRECTION\n"
3023 "uniform half3 LightColor : register(c21),\n"
3025 "#ifdef MODE_LIGHTSOURCE\n"
3026 "uniform half3 LightColor : register(c21),\n"
3029 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3030 "uniform sampler Texture_Attenuation : register(s9),\n"
3031 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3034 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3036 "#ifdef USESHADOWMAP2D\n"
3037 "# ifdef USESHADOWSAMPLER\n"
3038 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3040 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3044 "#ifdef USESHADOWMAPVSDCT\n"
3045 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3048 "#if defined(USESHADOWMAP2D)\n"
3049 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3050 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3052 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3054 "out float4 gl_FragColor : COLOR\n"
3057 " float2 TexCoord = TexCoordBoth.xy;\n"
3058 "#ifdef USEVERTEXTEXTUREBLEND\n"
3059 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3061 "#ifdef USEOFFSETMAPPING\n"
3062 " // apply offsetmapping\n"
3063 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3064 "#define TexCoord TexCoordOffset\n"
3067 " // combine the diffuse textures (base, pants, shirt)\n"
3068 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3069 "#ifdef USEALPHAKILL\n"
3070 " if (color.a < 0.5)\n"
3073 " color.a *= Alpha;\n"
3074 "#ifdef USECOLORMAPPING\n"
3075 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3077 "#ifdef USEVERTEXTEXTUREBLEND\n"
3078 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3079 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3080 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3081 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3083 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3086 " // get the surface normal\n"
3087 "#ifdef USEVERTEXTEXTUREBLEND\n"
3088 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3090 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3093 " // get the material colors\n"
3094 " half3 diffusetex = color.rgb;\n"
3095 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3096 "# ifdef USEVERTEXTEXTUREBLEND\n"
3097 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3099 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3103 "#ifdef USEREFLECTCUBE\n"
3104 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3105 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3106 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3107 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3113 "#ifdef MODE_LIGHTSOURCE\n"
3114 " // light source\n"
3115 "#ifdef USEDIFFUSE\n"
3116 " half3 lightnormal = half3(normalize(LightVector));\n"
3117 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3118 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3119 "#ifdef USESPECULAR\n"
3120 "#ifdef USEEXACTSPECULARMATH\n"
3121 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3123 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3124 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3126 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3129 " color.rgb = diffusetex * Color_Ambient;\n"
3131 " color.rgb *= LightColor;\n"
3132 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3133 "#if defined(USESHADOWMAP2D)\n"
3134 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3135 "#ifdef USESHADOWMAPVSDCT\n"
3136 ", Texture_CubeProjection\n"
3141 "# ifdef USECUBEFILTER\n"
3142 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3145 "#ifdef USESHADOWMAP2D\n"
3146 "#ifdef USESHADOWMAPVSDCT\n"
3147 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3149 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3151 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3152 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3153 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3154 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3155 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3156 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3157 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3158 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3159 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3160 "// color.r = half(shadowmaptc.z);\n"
3161 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3162 "// color.r = half(shadowmaptc.z);\n"
3164 "// color.rgb = abs(CubeVector);\n"
3166 "// color.rgb = half3(1,1,1);\n"
3167 "#endif // MODE_LIGHTSOURCE\n"
3172 "#ifdef MODE_LIGHTDIRECTION\n"
3174 "#ifdef USEDIFFUSE\n"
3175 " half3 lightnormal = half3(normalize(LightVector));\n"
3177 "#define lightcolor LightColor\n"
3178 "#endif // MODE_LIGHTDIRECTION\n"
3179 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3181 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3182 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3183 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3184 " // convert modelspace light vector to tangentspace\n"
3185 " half3 lightnormal;\n"
3186 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3187 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3188 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3189 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3190 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3191 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3192 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3193 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3194 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3195 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3196 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3197 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3198 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3199 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3200 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3202 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3203 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3204 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3210 "#ifdef MODE_FAKELIGHT\n"
3212 "half3 lightnormal = half3(normalize(EyeVector));\n"
3213 "half3 lightcolor = half3(1.0);\n"
3214 "#endif // MODE_FAKELIGHT\n"
3219 "#ifdef MODE_LIGHTMAP\n"
3220 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3221 "#endif // MODE_LIGHTMAP\n"
3222 "#ifdef MODE_VERTEXCOLOR\n"
3223 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3224 "#endif // MODE_VERTEXCOLOR\n"
3225 "#ifdef MODE_FLATCOLOR\n"
3226 " color.rgb = diffusetex * Color_Ambient;\n"
3227 "#endif // MODE_FLATCOLOR\n"
3233 "# ifdef USEDIFFUSE\n"
3234 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3235 "# ifdef USESPECULAR\n"
3236 "# ifdef USEEXACTSPECULARMATH\n"
3237 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3239 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3240 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3242 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3244 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3247 " color.rgb = diffusetex * Color_Ambient;\n"
3251 "#ifdef USESHADOWMAPORTHO\n"
3252 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3255 "#ifdef USEDEFERREDLIGHTMAP\n"
3256 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3257 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3258 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3259 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3260 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3264 "#ifdef USEVERTEXTEXTUREBLEND\n"
3265 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3267 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3272 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3275 " // 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"
3276 "#ifdef USEREFLECTION\n"
3277 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3278 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3279 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3280 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3281 " // FIXME temporary hack to detect the case that the reflection\n"
3282 " // gets blackened at edges due to leaving the area that contains actual\n"
3284 " // Remove this 'ack once we have a better way to stop this thing from\n"
3286 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3287 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3288 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3289 " f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3290 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3291 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3294 " gl_FragColor = float4(color);\n"
3296 "#endif // FRAGMENT_SHADER\n"
3298 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3299 "#endif // !MODE_DEFERREDGEOMETRY\n"
3300 "#endif // !MODE_WATER\n"
3301 "#endif // !MODE_REFRACTION\n"
3302 "#endif // !MODE_BLOOMBLUR\n"
3303 "#endif // !MODE_GENERIC\n"
3304 "#endif // !MODE_POSTPROCESS\n"
3305 "#endif // !MODE_SHOWDEPTH\n"
3306 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3309 char *glslshaderstring = NULL;
3310 char *cgshaderstring = NULL;
3311 char *hlslshaderstring = NULL;
3313 //=======================================================================================================================================================
3315 typedef struct shaderpermutationinfo_s
3317 const char *pretext;
3320 shaderpermutationinfo_t;
3322 typedef struct shadermodeinfo_s
3324 const char *vertexfilename;
3325 const char *geometryfilename;
3326 const char *fragmentfilename;
3327 const char *pretext;
3332 typedef enum shaderpermutation_e
3334 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3335 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3336 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3337 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3338 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3339 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3340 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3341 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3342 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3343 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3344 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3345 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3346 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3347 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3348 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3349 SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3350 SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3351 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3352 SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3353 SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3354 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3355 SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3356 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3357 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3358 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3359 SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3360 SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3361 SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<27, // (water) counter-direction normalmaps scrolling
3362 SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3363 SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3365 shaderpermutation_t;
3367 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3368 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3370 {"#define USEDIFFUSE\n", " diffuse"},
3371 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3372 {"#define USEVIEWTINT\n", " viewtint"},
3373 {"#define USECOLORMAPPING\n", " colormapping"},
3374 {"#define USESATURATION\n", " saturation"},
3375 {"#define USEFOGINSIDE\n", " foginside"},
3376 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3377 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3378 {"#define USEGAMMARAMPS\n", " gammaramps"},
3379 {"#define USECUBEFILTER\n", " cubefilter"},
3380 {"#define USEGLOW\n", " glow"},
3381 {"#define USEBLOOM\n", " bloom"},
3382 {"#define USESPECULAR\n", " specular"},
3383 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3384 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3385 {"#define USEREFLECTION\n", " reflection"},
3386 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3387 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3388 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3389 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3390 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3391 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3392 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3393 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3394 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3395 {"#define USEALPHAKILL\n", " alphakill"},
3396 {"#define USEREFLECTCUBE\n", " reflectcube"},
3397 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3400 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3401 typedef enum shadermode_e
3403 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3404 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3405 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3406 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3407 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3408 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3409 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3410 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3411 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3412 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3413 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3414 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3415 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3416 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3417 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3418 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3423 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3424 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3426 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3427 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3428 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3429 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3430 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3431 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3432 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3433 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3434 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3435 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3436 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3437 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3438 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3439 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3440 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3441 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3445 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3447 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3448 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3449 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3450 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3451 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3452 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3453 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3454 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3455 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3456 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3457 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3458 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3459 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3460 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3461 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3462 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3467 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3469 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3470 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3471 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3472 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3473 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3474 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3475 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3476 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3477 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3478 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3479 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3481 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3482 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3483 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3487 struct r_glsl_permutation_s;
3488 typedef struct r_glsl_permutation_s
3490 /// hash lookup data
3491 struct r_glsl_permutation_s *hashnext;
3493 unsigned int permutation;
3495 /// indicates if we have tried compiling this permutation already
3497 /// 0 if compilation failed
3499 /// locations of detected uniforms in program object, or -1 if not found
3500 int loc_Texture_First;
3501 int loc_Texture_Second;
3502 int loc_Texture_GammaRamps;
3503 int loc_Texture_Normal;
3504 int loc_Texture_Color;
3505 int loc_Texture_Gloss;
3506 int loc_Texture_Glow;
3507 int loc_Texture_SecondaryNormal;
3508 int loc_Texture_SecondaryColor;
3509 int loc_Texture_SecondaryGloss;
3510 int loc_Texture_SecondaryGlow;
3511 int loc_Texture_Pants;
3512 int loc_Texture_Shirt;
3513 int loc_Texture_FogHeightTexture;
3514 int loc_Texture_FogMask;
3515 int loc_Texture_Lightmap;
3516 int loc_Texture_Deluxemap;
3517 int loc_Texture_Attenuation;
3518 int loc_Texture_Cube;
3519 int loc_Texture_Refraction;
3520 int loc_Texture_Reflection;
3521 int loc_Texture_ShadowMap2D;
3522 int loc_Texture_CubeProjection;
3523 int loc_Texture_ScreenDepth;
3524 int loc_Texture_ScreenNormalMap;
3525 int loc_Texture_ScreenDiffuse;
3526 int loc_Texture_ScreenSpecular;
3527 int loc_Texture_ReflectMask;
3528 int loc_Texture_ReflectCube;
3530 int loc_BloomBlur_Parameters;
3532 int loc_Color_Ambient;
3533 int loc_Color_Diffuse;
3534 int loc_Color_Specular;
3536 int loc_Color_Pants;
3537 int loc_Color_Shirt;
3538 int loc_DeferredColor_Ambient;
3539 int loc_DeferredColor_Diffuse;
3540 int loc_DeferredColor_Specular;
3541 int loc_DeferredMod_Diffuse;
3542 int loc_DeferredMod_Specular;
3543 int loc_DistortScaleRefractReflect;
3544 int loc_EyePosition;
3546 int loc_FogHeightFade;
3548 int loc_FogPlaneViewDist;
3549 int loc_FogRangeRecip;
3552 int loc_LightPosition;
3553 int loc_OffsetMapping_Scale;
3555 int loc_ReflectColor;
3556 int loc_ReflectFactor;
3557 int loc_ReflectOffset;
3558 int loc_RefractColor;
3560 int loc_ScreenCenterRefractReflect;
3561 int loc_ScreenScaleRefractReflect;
3562 int loc_ScreenToDepth;
3563 int loc_ShadowMap_Parameters;
3564 int loc_ShadowMap_TextureScale;
3565 int loc_SpecularPower;
3570 int loc_ViewTintColor;
3571 int loc_ViewToLight;
3572 int loc_ModelToLight;
3574 int loc_BackgroundTexMatrix;
3575 int loc_ModelViewProjectionMatrix;
3576 int loc_ModelViewMatrix;
3577 int loc_PixelToScreenTexCoord;
3578 int loc_ModelToReflectCube;
3579 int loc_ShadowMapMatrix;
3580 int loc_BloomColorSubtract;
3581 int loc_NormalmapScrollBlend;
3583 r_glsl_permutation_t;
3585 #define SHADERPERMUTATION_HASHSIZE 256
3588 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3589 // these can NOT degrade! only use for simple stuff
3592 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0
3594 #define SHADERSTATICPARMS_COUNT 1
3596 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3597 static int shaderstaticparms_count = 0;
3599 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3600 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3601 qboolean R_CompileShader_CheckStaticParms(void)
3603 static int r_compileshader_staticparms_save[1];
3604 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3605 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3608 if (r_glsl_saturation_redcompensate.integer)
3609 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3611 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms));
3614 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3615 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3616 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3618 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3619 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3621 shaderstaticparms_count = 0;
3624 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3628 /// information about each possible shader permutation
3629 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3630 /// currently selected permutation
3631 r_glsl_permutation_t *r_glsl_permutation;
3632 /// storage for permutations linked in the hash table
3633 memexpandablearray_t r_glsl_permutationarray;
3635 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3637 //unsigned int hashdepth = 0;
3638 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3639 r_glsl_permutation_t *p;
3640 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3642 if (p->mode == mode && p->permutation == permutation)
3644 //if (hashdepth > 10)
3645 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3650 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3652 p->permutation = permutation;
3653 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3654 r_glsl_permutationhash[mode][hashindex] = p;
3655 //if (hashdepth > 10)
3656 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3660 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3663 if (!filename || !filename[0])
3665 if (!strcmp(filename, "glsl/default.glsl"))
3667 if (!glslshaderstring)
3669 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3670 if (glslshaderstring)
3671 Con_DPrintf("Loading shaders from file %s...\n", filename);
3673 glslshaderstring = (char *)builtinshaderstring;
3675 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3676 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3677 return shaderstring;
3679 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3682 if (printfromdisknotice)
3683 Con_DPrintf("from disk %s... ", filename);
3684 return shaderstring;
3686 return shaderstring;
3689 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3692 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3693 char *vertexstring, *geometrystring, *fragmentstring;
3694 char permutationname[256];
3695 int vertstrings_count = 0;
3696 int geomstrings_count = 0;
3697 int fragstrings_count = 0;
3698 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3699 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3700 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3707 permutationname[0] = 0;
3708 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3709 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3710 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3712 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3714 // the first pretext is which type of shader to compile as
3715 // (later these will all be bound together as a program object)
3716 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3717 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3718 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3720 // the second pretext is the mode (for example a light source)
3721 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3722 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3723 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3724 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3726 // now add all the permutation pretexts
3727 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3729 if (permutation & (1<<i))
3731 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3732 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3733 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3734 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3738 // keep line numbers correct
3739 vertstrings_list[vertstrings_count++] = "\n";
3740 geomstrings_list[geomstrings_count++] = "\n";
3741 fragstrings_list[fragstrings_count++] = "\n";
3746 R_CompileShader_AddStaticParms(mode, permutation);
3747 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3748 vertstrings_count += shaderstaticparms_count;
3749 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3750 geomstrings_count += shaderstaticparms_count;
3751 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3752 fragstrings_count += shaderstaticparms_count;
3754 // now append the shader text itself
3755 vertstrings_list[vertstrings_count++] = vertexstring;
3756 geomstrings_list[geomstrings_count++] = geometrystring;
3757 fragstrings_list[fragstrings_count++] = fragmentstring;
3759 // if any sources were NULL, clear the respective list
3761 vertstrings_count = 0;
3762 if (!geometrystring)
3763 geomstrings_count = 0;
3764 if (!fragmentstring)
3765 fragstrings_count = 0;
3767 // compile the shader program
3768 if (vertstrings_count + geomstrings_count + fragstrings_count)
3769 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3773 qglUseProgramObjectARB(p->program);CHECKGLERROR
3774 // look up all the uniform variable names we care about, so we don't
3775 // have to look them up every time we set them
3777 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3778 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3779 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3780 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3781 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3782 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3783 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3784 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3785 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3786 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3787 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3788 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3789 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3790 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3791 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3792 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3793 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3794 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3795 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3796 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3797 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3798 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3799 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3800 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3801 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3802 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3803 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3804 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3805 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3806 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3807 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3808 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3809 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3810 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3811 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3812 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3813 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3814 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3815 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3816 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3817 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3818 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3819 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3820 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3821 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3822 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3823 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3824 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3825 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3826 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3827 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3828 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3829 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3830 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3831 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3832 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3833 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3834 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3835 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3836 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3837 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3838 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3839 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3840 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3841 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3842 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3843 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3844 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3845 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3846 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3847 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3848 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3849 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3850 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3851 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3852 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3853 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3854 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3855 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3856 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3857 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3858 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3859 // initialize the samplers to refer to the texture units we use
3860 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3861 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3862 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3863 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3864 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3865 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3866 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3867 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3868 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3869 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3870 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3871 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3872 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3873 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3874 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3875 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3876 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3877 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3878 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3879 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3880 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3881 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3882 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3883 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3884 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3885 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3886 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3887 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3888 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3890 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3893 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3897 Mem_Free(vertexstring);
3899 Mem_Free(geometrystring);
3901 Mem_Free(fragmentstring);
3904 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3906 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3907 if (r_glsl_permutation != perm)
3909 r_glsl_permutation = perm;
3910 if (!r_glsl_permutation->program)
3912 if (!r_glsl_permutation->compiled)
3913 R_GLSL_CompilePermutation(perm, mode, permutation);
3914 if (!r_glsl_permutation->program)
3916 // remove features until we find a valid permutation
3918 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3920 // reduce i more quickly whenever it would not remove any bits
3921 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3922 if (!(permutation & j))
3925 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3926 if (!r_glsl_permutation->compiled)
3927 R_GLSL_CompilePermutation(perm, mode, permutation);
3928 if (r_glsl_permutation->program)
3931 if (i >= SHADERPERMUTATION_COUNT)
3933 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3934 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3935 qglUseProgramObjectARB(0);CHECKGLERROR
3936 return; // no bit left to clear, entire mode is broken
3941 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3943 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3944 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3945 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3949 #include <Cg/cgGL.h>
3950 struct r_cg_permutation_s;
3951 typedef struct r_cg_permutation_s
3953 /// hash lookup data
3954 struct r_cg_permutation_s *hashnext;
3956 unsigned int permutation;
3958 /// indicates if we have tried compiling this permutation already
3960 /// 0 if compilation failed
3963 /// locations of detected parameters in programs, or NULL if not found
3964 CGparameter vp_EyePosition;
3965 CGparameter vp_FogPlane;
3966 CGparameter vp_LightDir;
3967 CGparameter vp_LightPosition;
3968 CGparameter vp_ModelToLight;
3969 CGparameter vp_TexMatrix;
3970 CGparameter vp_BackgroundTexMatrix;
3971 CGparameter vp_ModelViewProjectionMatrix;
3972 CGparameter vp_ModelViewMatrix;
3973 CGparameter vp_ShadowMapMatrix;
3975 CGparameter fp_Texture_First;
3976 CGparameter fp_Texture_Second;
3977 CGparameter fp_Texture_GammaRamps;
3978 CGparameter fp_Texture_Normal;
3979 CGparameter fp_Texture_Color;
3980 CGparameter fp_Texture_Gloss;
3981 CGparameter fp_Texture_Glow;
3982 CGparameter fp_Texture_SecondaryNormal;
3983 CGparameter fp_Texture_SecondaryColor;
3984 CGparameter fp_Texture_SecondaryGloss;
3985 CGparameter fp_Texture_SecondaryGlow;
3986 CGparameter fp_Texture_Pants;
3987 CGparameter fp_Texture_Shirt;
3988 CGparameter fp_Texture_FogHeightTexture;
3989 CGparameter fp_Texture_FogMask;
3990 CGparameter fp_Texture_Lightmap;
3991 CGparameter fp_Texture_Deluxemap;
3992 CGparameter fp_Texture_Attenuation;
3993 CGparameter fp_Texture_Cube;
3994 CGparameter fp_Texture_Refraction;
3995 CGparameter fp_Texture_Reflection;
3996 CGparameter fp_Texture_ShadowMap2D;
3997 CGparameter fp_Texture_CubeProjection;
3998 CGparameter fp_Texture_ScreenDepth;
3999 CGparameter fp_Texture_ScreenNormalMap;
4000 CGparameter fp_Texture_ScreenDiffuse;
4001 CGparameter fp_Texture_ScreenSpecular;
4002 CGparameter fp_Texture_ReflectMask;
4003 CGparameter fp_Texture_ReflectCube;
4004 CGparameter fp_Alpha;
4005 CGparameter fp_BloomBlur_Parameters;
4006 CGparameter fp_ClientTime;
4007 CGparameter fp_Color_Ambient;
4008 CGparameter fp_Color_Diffuse;
4009 CGparameter fp_Color_Specular;
4010 CGparameter fp_Color_Glow;
4011 CGparameter fp_Color_Pants;
4012 CGparameter fp_Color_Shirt;
4013 CGparameter fp_DeferredColor_Ambient;
4014 CGparameter fp_DeferredColor_Diffuse;
4015 CGparameter fp_DeferredColor_Specular;
4016 CGparameter fp_DeferredMod_Diffuse;
4017 CGparameter fp_DeferredMod_Specular;
4018 CGparameter fp_DistortScaleRefractReflect;
4019 CGparameter fp_EyePosition;
4020 CGparameter fp_FogColor;
4021 CGparameter fp_FogHeightFade;
4022 CGparameter fp_FogPlane;
4023 CGparameter fp_FogPlaneViewDist;
4024 CGparameter fp_FogRangeRecip;
4025 CGparameter fp_LightColor;
4026 CGparameter fp_LightDir;
4027 CGparameter fp_LightPosition;
4028 CGparameter fp_OffsetMapping_Scale;
4029 CGparameter fp_PixelSize;
4030 CGparameter fp_ReflectColor;
4031 CGparameter fp_ReflectFactor;
4032 CGparameter fp_ReflectOffset;
4033 CGparameter fp_RefractColor;
4034 CGparameter fp_Saturation;
4035 CGparameter fp_ScreenCenterRefractReflect;
4036 CGparameter fp_ScreenScaleRefractReflect;
4037 CGparameter fp_ScreenToDepth;
4038 CGparameter fp_ShadowMap_Parameters;
4039 CGparameter fp_ShadowMap_TextureScale;
4040 CGparameter fp_SpecularPower;
4041 CGparameter fp_UserVec1;
4042 CGparameter fp_UserVec2;
4043 CGparameter fp_UserVec3;
4044 CGparameter fp_UserVec4;
4045 CGparameter fp_ViewTintColor;
4046 CGparameter fp_ViewToLight;
4047 CGparameter fp_PixelToScreenTexCoord;
4048 CGparameter fp_ModelToReflectCube;
4049 CGparameter fp_BloomColorSubtract;
4050 CGparameter fp_NormalmapScrollBlend;
4054 /// information about each possible shader permutation
4055 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4056 /// currently selected permutation
4057 r_cg_permutation_t *r_cg_permutation;
4058 /// storage for permutations linked in the hash table
4059 memexpandablearray_t r_cg_permutationarray;
4061 #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));}}
4063 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4065 //unsigned int hashdepth = 0;
4066 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4067 r_cg_permutation_t *p;
4068 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4070 if (p->mode == mode && p->permutation == permutation)
4072 //if (hashdepth > 10)
4073 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4078 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4080 p->permutation = permutation;
4081 p->hashnext = r_cg_permutationhash[mode][hashindex];
4082 r_cg_permutationhash[mode][hashindex] = p;
4083 //if (hashdepth > 10)
4084 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4088 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4091 if (!filename || !filename[0])
4093 if (!strcmp(filename, "cg/default.cg"))
4095 if (!cgshaderstring)
4097 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4099 Con_DPrintf("Loading shaders from file %s...\n", filename);
4101 cgshaderstring = (char *)builtincgshaderstring;
4103 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4104 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4105 return shaderstring;
4107 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4110 if (printfromdisknotice)
4111 Con_DPrintf("from disk %s... ", filename);
4112 return shaderstring;
4114 return shaderstring;
4117 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4119 // TODO: load or create .fp and .vp shader files
4122 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4125 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4126 int vertstring_length = 0;
4127 int geomstring_length = 0;
4128 int fragstring_length = 0;
4130 char *vertexstring, *geometrystring, *fragmentstring;
4131 char *vertstring, *geomstring, *fragstring;
4132 char permutationname[256];
4133 char cachename[256];
4134 CGprofile vertexProfile;
4135 CGprofile fragmentProfile;
4136 int vertstrings_count = 0;
4137 int geomstrings_count = 0;
4138 int fragstrings_count = 0;
4139 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4140 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4141 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4149 permutationname[0] = 0;
4151 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4152 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4153 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4155 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4156 strlcat(cachename, "cg/", sizeof(cachename));
4158 // the first pretext is which type of shader to compile as
4159 // (later these will all be bound together as a program object)
4160 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4161 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4162 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4164 // the second pretext is the mode (for example a light source)
4165 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4166 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4167 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4168 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4169 strlcat(cachename, modeinfo->name, sizeof(cachename));
4171 // now add all the permutation pretexts
4172 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4174 if (permutation & (1<<i))
4176 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4177 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4178 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4179 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4180 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4184 // keep line numbers correct
4185 vertstrings_list[vertstrings_count++] = "\n";
4186 geomstrings_list[geomstrings_count++] = "\n";
4187 fragstrings_list[fragstrings_count++] = "\n";
4192 R_CompileShader_AddStaticParms(mode, permutation);
4193 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4194 vertstrings_count += shaderstaticparms_count;
4195 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4196 geomstrings_count += shaderstaticparms_count;
4197 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4198 fragstrings_count += shaderstaticparms_count;
4200 // replace spaces in the cachename with _ characters
4201 for (i = 0;cachename[i];i++)
4202 if (cachename[i] == ' ')
4205 // now append the shader text itself
4206 vertstrings_list[vertstrings_count++] = vertexstring;
4207 geomstrings_list[geomstrings_count++] = geometrystring;
4208 fragstrings_list[fragstrings_count++] = fragmentstring;
4210 // if any sources were NULL, clear the respective list
4212 vertstrings_count = 0;
4213 if (!geometrystring)
4214 geomstrings_count = 0;
4215 if (!fragmentstring)
4216 fragstrings_count = 0;
4218 vertstring_length = 0;
4219 for (i = 0;i < vertstrings_count;i++)
4220 vertstring_length += strlen(vertstrings_list[i]);
4221 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4222 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4223 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4225 geomstring_length = 0;
4226 for (i = 0;i < geomstrings_count;i++)
4227 geomstring_length += strlen(geomstrings_list[i]);
4228 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4229 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4230 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4232 fragstring_length = 0;
4233 for (i = 0;i < fragstrings_count;i++)
4234 fragstring_length += strlen(fragstrings_list[i]);
4235 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4236 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4237 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4241 //vertexProfile = CG_PROFILE_ARBVP1;
4242 //fragmentProfile = CG_PROFILE_ARBFP1;
4243 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4244 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4245 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4246 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4247 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4250 // try to load the cached shader, or generate one
4251 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4253 // if caching failed, do a dynamic compile for now
4255 if (vertstring[0] && !p->vprogram)
4256 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4258 if (fragstring[0] && !p->fprogram)
4259 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4262 // look up all the uniform variable names we care about, so we don't
4263 // have to look them up every time we set them
4267 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4268 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4269 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4270 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4271 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4272 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4273 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4274 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4275 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4276 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4277 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4278 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4284 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4285 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4286 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4287 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4288 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4289 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4290 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4291 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4292 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4293 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4294 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4295 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4296 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4297 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4298 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4299 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4300 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4301 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4302 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4303 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4304 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4305 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4306 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4307 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4308 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4309 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4310 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4311 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4312 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4313 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4314 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4315 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4316 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4317 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4318 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4319 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4320 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4321 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4322 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4323 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4324 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4325 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4326 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4327 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4328 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4329 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4330 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4331 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4332 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4333 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4334 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4335 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4336 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4337 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4338 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4339 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4340 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4341 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4342 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4343 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4344 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4345 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4346 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4347 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4348 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4349 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4350 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4351 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4352 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4353 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4354 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4355 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4356 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4357 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4358 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4359 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4360 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4361 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4365 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4366 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4368 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4372 Mem_Free(vertstring);
4374 Mem_Free(geomstring);
4376 Mem_Free(fragstring);
4378 Mem_Free(vertexstring);
4380 Mem_Free(geometrystring);
4382 Mem_Free(fragmentstring);
4385 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4387 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4390 if (r_cg_permutation != perm)
4392 r_cg_permutation = perm;
4393 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4395 if (!r_cg_permutation->compiled)
4396 R_CG_CompilePermutation(perm, mode, permutation);
4397 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4399 // remove features until we find a valid permutation
4401 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4403 // reduce i more quickly whenever it would not remove any bits
4404 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4405 if (!(permutation & j))
4408 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4409 if (!r_cg_permutation->compiled)
4410 R_CG_CompilePermutation(perm, mode, permutation);
4411 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4414 if (i >= SHADERPERMUTATION_COUNT)
4416 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4417 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4418 return; // no bit left to clear, entire mode is broken
4424 if (r_cg_permutation->vprogram)
4426 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4427 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4428 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4432 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4433 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4435 if (r_cg_permutation->fprogram)
4437 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4438 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4439 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4443 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4444 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4448 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4449 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4450 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4453 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4455 cgGLSetTextureParameter(param, R_GetTexture(tex));
4456 cgGLEnableTextureParameter(param);
4464 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4465 extern D3DCAPS9 vid_d3d9caps;
4468 struct r_hlsl_permutation_s;
4469 typedef struct r_hlsl_permutation_s
4471 /// hash lookup data
4472 struct r_hlsl_permutation_s *hashnext;
4474 unsigned int permutation;
4476 /// indicates if we have tried compiling this permutation already
4478 /// NULL if compilation failed
4479 IDirect3DVertexShader9 *vertexshader;
4480 IDirect3DPixelShader9 *pixelshader;
4482 r_hlsl_permutation_t;
4484 typedef enum D3DVSREGISTER_e
4486 D3DVSREGISTER_TexMatrix = 0, // float4x4
4487 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4488 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4489 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4490 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4491 D3DVSREGISTER_ModelToLight = 20, // float4x4
4492 D3DVSREGISTER_EyePosition = 24,
4493 D3DVSREGISTER_FogPlane = 25,
4494 D3DVSREGISTER_LightDir = 26,
4495 D3DVSREGISTER_LightPosition = 27,
4499 typedef enum D3DPSREGISTER_e
4501 D3DPSREGISTER_Alpha = 0,
4502 D3DPSREGISTER_BloomBlur_Parameters = 1,
4503 D3DPSREGISTER_ClientTime = 2,
4504 D3DPSREGISTER_Color_Ambient = 3,
4505 D3DPSREGISTER_Color_Diffuse = 4,
4506 D3DPSREGISTER_Color_Specular = 5,
4507 D3DPSREGISTER_Color_Glow = 6,
4508 D3DPSREGISTER_Color_Pants = 7,
4509 D3DPSREGISTER_Color_Shirt = 8,
4510 D3DPSREGISTER_DeferredColor_Ambient = 9,
4511 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4512 D3DPSREGISTER_DeferredColor_Specular = 11,
4513 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4514 D3DPSREGISTER_DeferredMod_Specular = 13,
4515 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4516 D3DPSREGISTER_EyePosition = 15, // unused
4517 D3DPSREGISTER_FogColor = 16,
4518 D3DPSREGISTER_FogHeightFade = 17,
4519 D3DPSREGISTER_FogPlane = 18,
4520 D3DPSREGISTER_FogPlaneViewDist = 19,
4521 D3DPSREGISTER_FogRangeRecip = 20,
4522 D3DPSREGISTER_LightColor = 21,
4523 D3DPSREGISTER_LightDir = 22, // unused
4524 D3DPSREGISTER_LightPosition = 23,
4525 D3DPSREGISTER_OffsetMapping_Scale = 24,
4526 D3DPSREGISTER_PixelSize = 25,
4527 D3DPSREGISTER_ReflectColor = 26,
4528 D3DPSREGISTER_ReflectFactor = 27,
4529 D3DPSREGISTER_ReflectOffset = 28,
4530 D3DPSREGISTER_RefractColor = 29,
4531 D3DPSREGISTER_Saturation = 30,
4532 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4533 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4534 D3DPSREGISTER_ScreenToDepth = 33,
4535 D3DPSREGISTER_ShadowMap_Parameters = 34,
4536 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4537 D3DPSREGISTER_SpecularPower = 36,
4538 D3DPSREGISTER_UserVec1 = 37,
4539 D3DPSREGISTER_UserVec2 = 38,
4540 D3DPSREGISTER_UserVec3 = 39,
4541 D3DPSREGISTER_UserVec4 = 40,
4542 D3DPSREGISTER_ViewTintColor = 41,
4543 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4544 D3DPSREGISTER_BloomColorSubtract = 43,
4545 D3DPSREGISTER_ViewToLight = 44, // float4x4
4546 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4547 D3DPSREGISTER_NormalmapScrollBlend = 52,
4552 /// information about each possible shader permutation
4553 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4554 /// currently selected permutation
4555 r_hlsl_permutation_t *r_hlsl_permutation;
4556 /// storage for permutations linked in the hash table
4557 memexpandablearray_t r_hlsl_permutationarray;
4559 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4561 //unsigned int hashdepth = 0;
4562 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4563 r_hlsl_permutation_t *p;
4564 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4566 if (p->mode == mode && p->permutation == permutation)
4568 //if (hashdepth > 10)
4569 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4574 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4576 p->permutation = permutation;
4577 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4578 r_hlsl_permutationhash[mode][hashindex] = p;
4579 //if (hashdepth > 10)
4580 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4584 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4587 if (!filename || !filename[0])
4589 if (!strcmp(filename, "hlsl/default.hlsl"))
4591 if (!hlslshaderstring)
4593 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4594 if (hlslshaderstring)
4595 Con_DPrintf("Loading shaders from file %s...\n", filename);
4597 hlslshaderstring = (char *)builtincgshaderstring;
4599 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4600 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4601 return shaderstring;
4603 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4606 if (printfromdisknotice)
4607 Con_DPrintf("from disk %s... ", filename);
4608 return shaderstring;
4610 return shaderstring;
4614 //#include <d3dx9shader.h>
4615 //#include <d3dx9mesh.h>
4617 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4619 DWORD *vsbin = NULL;
4620 DWORD *psbin = NULL;
4621 fs_offset_t vsbinsize;
4622 fs_offset_t psbinsize;
4623 // IDirect3DVertexShader9 *vs = NULL;
4624 // IDirect3DPixelShader9 *ps = NULL;
4625 ID3DXBuffer *vslog = NULL;
4626 ID3DXBuffer *vsbuffer = NULL;
4627 ID3DXConstantTable *vsconstanttable = NULL;
4628 ID3DXBuffer *pslog = NULL;
4629 ID3DXBuffer *psbuffer = NULL;
4630 ID3DXConstantTable *psconstanttable = NULL;
4633 char temp[MAX_INPUTLINE];
4634 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4635 qboolean debugshader = gl_paranoid.integer != 0;
4636 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4637 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4640 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4641 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4643 if ((!vsbin && vertstring) || (!psbin && fragstring))
4645 const char* dllnames_d3dx9 [] =
4669 dllhandle_t d3dx9_dll = NULL;
4670 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4671 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4672 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4673 dllfunction_t d3dx9_dllfuncs[] =
4675 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4676 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4677 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4680 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4682 DWORD shaderflags = 0;
4684 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4685 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4686 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4687 if (vertstring && vertstring[0])
4691 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4692 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4693 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4694 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4697 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4700 vsbinsize = vsbuffer->GetBufferSize();
4701 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4702 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4703 vsbuffer->Release();
4707 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4708 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4712 if (fragstring && fragstring[0])
4716 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4717 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4718 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4719 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4722 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4725 psbinsize = psbuffer->GetBufferSize();
4726 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4727 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4728 psbuffer->Release();
4732 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4733 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4737 Sys_UnloadLibrary(&d3dx9_dll);
4740 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4744 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4745 if (FAILED(vsresult))
4746 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4747 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4748 if (FAILED(psresult))
4749 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4751 // free the shader data
4752 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4753 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4756 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4759 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4760 int vertstring_length = 0;
4761 int geomstring_length = 0;
4762 int fragstring_length = 0;
4764 char *vertexstring, *geometrystring, *fragmentstring;
4765 char *vertstring, *geomstring, *fragstring;
4766 char permutationname[256];
4767 char cachename[256];
4768 int vertstrings_count = 0;
4769 int geomstrings_count = 0;
4770 int fragstrings_count = 0;
4771 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4772 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4773 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4778 p->vertexshader = NULL;
4779 p->pixelshader = NULL;
4781 permutationname[0] = 0;
4783 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4784 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4785 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4787 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4788 strlcat(cachename, "hlsl/", sizeof(cachename));
4790 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4791 vertstrings_count = 0;
4792 geomstrings_count = 0;
4793 fragstrings_count = 0;
4794 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4795 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4796 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4798 // the first pretext is which type of shader to compile as
4799 // (later these will all be bound together as a program object)
4800 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4801 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4802 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4804 // the second pretext is the mode (for example a light source)
4805 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4806 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4807 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4808 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4809 strlcat(cachename, modeinfo->name, sizeof(cachename));
4811 // now add all the permutation pretexts
4812 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4814 if (permutation & (1<<i))
4816 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4817 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4818 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4819 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4820 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4824 // keep line numbers correct
4825 vertstrings_list[vertstrings_count++] = "\n";
4826 geomstrings_list[geomstrings_count++] = "\n";
4827 fragstrings_list[fragstrings_count++] = "\n";
4832 R_CompileShader_AddStaticParms(mode, permutation);
4833 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4834 vertstrings_count += shaderstaticparms_count;
4835 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4836 geomstrings_count += shaderstaticparms_count;
4837 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4838 fragstrings_count += shaderstaticparms_count;
4840 // replace spaces in the cachename with _ characters
4841 for (i = 0;cachename[i];i++)
4842 if (cachename[i] == ' ')
4845 // now append the shader text itself
4846 vertstrings_list[vertstrings_count++] = vertexstring;
4847 geomstrings_list[geomstrings_count++] = geometrystring;
4848 fragstrings_list[fragstrings_count++] = fragmentstring;
4850 // if any sources were NULL, clear the respective list
4852 vertstrings_count = 0;
4853 if (!geometrystring)
4854 geomstrings_count = 0;
4855 if (!fragmentstring)
4856 fragstrings_count = 0;
4858 vertstring_length = 0;
4859 for (i = 0;i < vertstrings_count;i++)
4860 vertstring_length += strlen(vertstrings_list[i]);
4861 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4862 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4863 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4865 geomstring_length = 0;
4866 for (i = 0;i < geomstrings_count;i++)
4867 geomstring_length += strlen(geomstrings_list[i]);
4868 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4869 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4870 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4872 fragstring_length = 0;
4873 for (i = 0;i < fragstrings_count;i++)
4874 fragstring_length += strlen(fragstrings_list[i]);
4875 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4876 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4877 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4879 // try to load the cached shader, or generate one
4880 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4882 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4883 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4885 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4889 Mem_Free(vertstring);
4891 Mem_Free(geomstring);
4893 Mem_Free(fragstring);
4895 Mem_Free(vertexstring);
4897 Mem_Free(geometrystring);
4899 Mem_Free(fragmentstring);
4902 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4903 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4904 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);}
4905 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);}
4906 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);}
4907 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);}
4909 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4910 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4911 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);}
4912 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);}
4913 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);}
4914 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);}
4916 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4918 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4919 if (r_hlsl_permutation != perm)
4921 r_hlsl_permutation = perm;
4922 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4924 if (!r_hlsl_permutation->compiled)
4925 R_HLSL_CompilePermutation(perm, mode, permutation);
4926 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4928 // remove features until we find a valid permutation
4930 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4932 // reduce i more quickly whenever it would not remove any bits
4933 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4934 if (!(permutation & j))
4937 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4938 if (!r_hlsl_permutation->compiled)
4939 R_HLSL_CompilePermutation(perm, mode, permutation);
4940 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4943 if (i >= SHADERPERMUTATION_COUNT)
4945 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4946 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4947 return; // no bit left to clear, entire mode is broken
4951 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4952 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4954 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4955 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4956 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4960 void R_GLSL_Restart_f(void)
4962 unsigned int i, limit;
4963 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4964 Mem_Free(glslshaderstring);
4965 glslshaderstring = NULL;
4966 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4967 Mem_Free(cgshaderstring);
4968 cgshaderstring = NULL;
4969 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4970 Mem_Free(hlslshaderstring);
4971 hlslshaderstring = NULL;
4972 switch(vid.renderpath)
4974 case RENDERPATH_D3D9:
4977 r_hlsl_permutation_t *p;
4978 r_hlsl_permutation = NULL;
4979 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4980 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4981 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4982 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4983 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4984 for (i = 0;i < limit;i++)
4986 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4988 if (p->vertexshader)
4989 IDirect3DVertexShader9_Release(p->vertexshader);
4991 IDirect3DPixelShader9_Release(p->pixelshader);
4992 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4995 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4999 case RENDERPATH_D3D10:
5000 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5002 case RENDERPATH_D3D11:
5003 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5005 case RENDERPATH_GL20:
5007 r_glsl_permutation_t *p;
5008 r_glsl_permutation = NULL;
5009 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5010 for (i = 0;i < limit;i++)
5012 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5014 GL_Backend_FreeProgram(p->program);
5015 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5018 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5021 case RENDERPATH_CGGL:
5024 r_cg_permutation_t *p;
5025 r_cg_permutation = NULL;
5026 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5027 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5028 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5029 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5030 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5031 for (i = 0;i < limit;i++)
5033 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5036 cgDestroyProgram(p->vprogram);
5038 cgDestroyProgram(p->fprogram);
5039 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5042 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5046 case RENDERPATH_GL13:
5047 case RENDERPATH_GL11:
5052 void R_GLSL_DumpShader_f(void)
5057 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5060 FS_Print(file, "/* The engine may define the following macros:\n");
5061 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5062 for (i = 0;i < SHADERMODE_COUNT;i++)
5063 FS_Print(file, glslshadermodeinfo[i].pretext);
5064 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5065 FS_Print(file, shaderpermutationinfo[i].pretext);
5066 FS_Print(file, "*/\n");
5067 FS_Print(file, builtinshaderstring);
5069 Con_Printf("glsl/default.glsl written\n");
5072 Con_Printf("failed to write to glsl/default.glsl\n");
5075 file = FS_OpenRealFile("cg/default.cg", "w", false);
5078 FS_Print(file, "/* The engine may define the following macros:\n");
5079 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5080 for (i = 0;i < SHADERMODE_COUNT;i++)
5081 FS_Print(file, cgshadermodeinfo[i].pretext);
5082 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5083 FS_Print(file, shaderpermutationinfo[i].pretext);
5084 FS_Print(file, "*/\n");
5085 FS_Print(file, builtincgshaderstring);
5087 Con_Printf("cg/default.cg written\n");
5090 Con_Printf("failed to write to cg/default.cg\n");
5094 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5097 FS_Print(file, "/* The engine may define the following macros:\n");
5098 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5099 for (i = 0;i < SHADERMODE_COUNT;i++)
5100 FS_Print(file, hlslshadermodeinfo[i].pretext);
5101 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5102 FS_Print(file, shaderpermutationinfo[i].pretext);
5103 FS_Print(file, "*/\n");
5104 FS_Print(file, builtincgshaderstring);
5106 Con_Printf("hlsl/default.hlsl written\n");
5109 Con_Printf("failed to write to hlsl/default.hlsl\n");
5113 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5116 texturemode = GL_MODULATE;
5117 switch (vid.renderpath)
5119 case RENDERPATH_D3D9:
5121 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))));
5122 R_Mesh_TexBind(GL20TU_FIRST , first );
5123 R_Mesh_TexBind(GL20TU_SECOND, second);
5126 case RENDERPATH_D3D10:
5127 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5129 case RENDERPATH_D3D11:
5130 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5132 case RENDERPATH_GL20:
5133 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))));
5134 R_Mesh_TexBind(GL20TU_FIRST , first );
5135 R_Mesh_TexBind(GL20TU_SECOND, second);
5137 case RENDERPATH_CGGL:
5140 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))));
5141 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5142 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5145 case RENDERPATH_GL13:
5146 R_Mesh_TexBind(0, first );
5147 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5148 R_Mesh_TexBind(1, second);
5150 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5152 case RENDERPATH_GL11:
5153 R_Mesh_TexBind(0, first );
5158 void R_SetupShader_DepthOrShadow(void)
5160 switch (vid.renderpath)
5162 case RENDERPATH_D3D9:
5164 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5167 case RENDERPATH_D3D10:
5168 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5170 case RENDERPATH_D3D11:
5171 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5173 case RENDERPATH_GL20:
5174 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5176 case RENDERPATH_CGGL:
5178 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5181 case RENDERPATH_GL13:
5182 R_Mesh_TexBind(0, 0);
5183 R_Mesh_TexBind(1, 0);
5185 case RENDERPATH_GL11:
5186 R_Mesh_TexBind(0, 0);
5191 void R_SetupShader_ShowDepth(void)
5193 switch (vid.renderpath)
5195 case RENDERPATH_D3D9:
5197 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5200 case RENDERPATH_D3D10:
5201 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5203 case RENDERPATH_D3D11:
5204 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5206 case RENDERPATH_GL20:
5207 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5209 case RENDERPATH_CGGL:
5211 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5214 case RENDERPATH_GL13:
5216 case RENDERPATH_GL11:
5221 extern qboolean r_shadow_usingdeferredprepass;
5222 extern cvar_t r_shadow_deferred_8bitrange;
5223 extern rtexture_t *r_shadow_attenuationgradienttexture;
5224 extern rtexture_t *r_shadow_attenuation2dtexture;
5225 extern rtexture_t *r_shadow_attenuation3dtexture;
5226 extern qboolean r_shadow_usingshadowmap2d;
5227 extern qboolean r_shadow_usingshadowmaportho;
5228 extern float r_shadow_shadowmap_texturescale[2];
5229 extern float r_shadow_shadowmap_parameters[4];
5230 extern qboolean r_shadow_shadowmapvsdct;
5231 extern qboolean r_shadow_shadowmapsampler;
5232 extern int r_shadow_shadowmappcf;
5233 extern rtexture_t *r_shadow_shadowmap2dtexture;
5234 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5235 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5236 extern matrix4x4_t r_shadow_shadowmapmatrix;
5237 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5238 extern int r_shadow_prepass_width;
5239 extern int r_shadow_prepass_height;
5240 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5241 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5242 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5243 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5244 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5245 extern cvar_t gl_mesh_separatearrays;
5246 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5248 // a blendfunc allows colormod if:
5249 // a) it can never keep the destination pixel invariant, or
5250 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5251 // this is to prevent unintended side effects from colormod
5254 // IF there is a (s, sa) for which for all (d, da),
5255 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5256 // THEN, for this (s, sa) and all (colormod, d, da):
5257 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5258 // OBVIOUSLY, this means that
5259 // s*colormod * src(s*colormod, d, sa, da) = 0
5260 // dst(s*colormod, d, sa, da) = 1
5262 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5264 // main condition to leave dst color invariant:
5265 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5267 // s * 0 + d * dst(s, d, sa, da) == d
5268 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5269 // => colormod is a problem for GL_SRC_COLOR only
5271 // s + d * dst(s, d, sa, da) == d
5273 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5274 // => colormod is never problematic for these
5275 // src == GL_SRC_COLOR:
5276 // s*s + d * dst(s, d, sa, da) == d
5278 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5279 // => colormod is never problematic for these
5280 // src == GL_ONE_MINUS_SRC_COLOR:
5281 // s*(1-s) + d * dst(s, d, sa, da) == d
5282 // => s == 0 or s == 1
5283 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5284 // => colormod is a problem for GL_SRC_COLOR only
5285 // src == GL_DST_COLOR
5286 // s*d + d * dst(s, d, sa, da) == d
5288 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5289 // => colormod is always a problem
5292 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5293 // => colormod is never problematic for these
5294 // => BUT, we do not know s! We must assume it is problematic
5295 // then... except in GL_ONE case, where we know all invariant
5297 // src == GL_ONE_MINUS_DST_COLOR
5298 // s*(1-d) + d * dst(s, d, sa, da) == d
5299 // => s == 0 (1-d is impossible to handle for our desired result)
5300 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301 // => colormod is never problematic for these
5302 // src == GL_SRC_ALPHA
5303 // s*sa + d * dst(s, d, sa, da) == d
5304 // => s == 0, or sa == 0
5305 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306 // => colormod breaks in the case GL_SRC_COLOR only
5307 // src == GL_ONE_MINUS_SRC_ALPHA
5308 // s*(1-sa) + d * dst(s, d, sa, da) == d
5309 // => s == 0, or sa == 1
5310 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311 // => colormod breaks in the case GL_SRC_COLOR only
5312 // src == GL_DST_ALPHA
5313 // s*da + d * dst(s, d, sa, da) == d
5315 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316 // => colormod is never problematic for these
5321 case GL_ONE_MINUS_SRC_COLOR:
5323 case GL_ONE_MINUS_SRC_ALPHA:
5324 if(dst == GL_SRC_COLOR)
5329 case GL_ONE_MINUS_DST_COLOR:
5331 case GL_ONE_MINUS_DST_ALPHA:
5341 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)
5343 // select a permutation of the lighting shader appropriate to this
5344 // combination of texture, entity, light source, and fogging, only use the
5345 // minimum features necessary to avoid wasting rendering time in the
5346 // fragment shader on features that are not being used
5347 unsigned int permutation = 0;
5348 unsigned int mode = 0;
5349 qboolean allow_colormod;
5350 static float dummy_colormod[3] = {1, 1, 1};
5351 float *colormod = rsurface.colormod;
5353 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5354 if (rsurfacepass == RSURFPASS_BACKGROUND)
5356 // distorted background
5357 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5359 mode = SHADERMODE_WATER;
5360 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5361 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5362 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5363 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5365 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5367 mode = SHADERMODE_REFRACTION;
5368 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5369 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5373 mode = SHADERMODE_GENERIC;
5374 permutation |= SHADERPERMUTATION_DIFFUSE;
5375 GL_BlendFunc(GL_ONE, GL_ZERO);
5376 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5378 GL_AlphaTest(false);
5380 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5382 if (r_glsl_offsetmapping.integer)
5384 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5385 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5386 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5387 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5388 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5390 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5391 if (r_glsl_offsetmapping_reliefmapping.integer)
5392 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5395 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5396 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5398 permutation |= SHADERPERMUTATION_ALPHAKILL;
5399 // normalmap (deferred prepass), may use alpha test on diffuse
5400 mode = SHADERMODE_DEFERREDGEOMETRY;
5401 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5402 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5403 GL_AlphaTest(false);
5404 GL_BlendFunc(GL_ONE, GL_ZERO);
5405 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5407 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5409 if (r_glsl_offsetmapping.integer)
5411 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5412 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5413 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5414 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5415 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5417 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5418 if (r_glsl_offsetmapping_reliefmapping.integer)
5419 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5422 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5423 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5425 mode = SHADERMODE_LIGHTSOURCE;
5426 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5427 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5428 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5429 permutation |= SHADERPERMUTATION_CUBEFILTER;
5430 if (diffusescale > 0)
5431 permutation |= SHADERPERMUTATION_DIFFUSE;
5432 if (specularscale > 0)
5434 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5435 if (r_shadow_glossexact.integer)
5436 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5438 if (r_refdef.fogenabled)
5439 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5440 if (rsurface.texture->colormapping)
5441 permutation |= SHADERPERMUTATION_COLORMAPPING;
5442 if (r_shadow_usingshadowmap2d)
5444 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5445 if(r_shadow_shadowmapvsdct)
5446 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5448 if (r_shadow_shadowmapsampler)
5449 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5450 if (r_shadow_shadowmappcf > 1)
5451 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5452 else if (r_shadow_shadowmappcf)
5453 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5455 if (rsurface.texture->reflectmasktexture)
5456 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5457 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5458 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5459 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5461 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5463 if (r_glsl_offsetmapping.integer)
5465 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5466 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5467 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5468 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5469 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5471 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5472 if (r_glsl_offsetmapping_reliefmapping.integer)
5473 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5476 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5477 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5478 // unshaded geometry (fullbright or ambient model lighting)
5479 mode = SHADERMODE_FLATCOLOR;
5480 ambientscale = diffusescale = specularscale = 0;
5481 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5482 permutation |= SHADERPERMUTATION_GLOW;
5483 if (r_refdef.fogenabled)
5484 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5485 if (rsurface.texture->colormapping)
5486 permutation |= SHADERPERMUTATION_COLORMAPPING;
5487 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5489 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5490 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5492 if (r_shadow_shadowmapsampler)
5493 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5494 if (r_shadow_shadowmappcf > 1)
5495 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5496 else if (r_shadow_shadowmappcf)
5497 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5499 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5500 permutation |= SHADERPERMUTATION_REFLECTION;
5501 if (rsurface.texture->reflectmasktexture)
5502 permutation |= SHADERPERMUTATION_REFLECTCUBE;
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);
5507 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5509 if (r_glsl_offsetmapping.integer)
5511 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5512 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5513 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5514 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5515 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5517 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5518 if (r_glsl_offsetmapping_reliefmapping.integer)
5519 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5522 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5523 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5524 // directional model lighting
5525 mode = SHADERMODE_LIGHTDIRECTION;
5526 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5527 permutation |= SHADERPERMUTATION_GLOW;
5528 permutation |= SHADERPERMUTATION_DIFFUSE;
5529 if (specularscale > 0)
5531 permutation |= SHADERPERMUTATION_SPECULAR;
5532 if (r_shadow_glossexact.integer)
5533 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5535 if (r_refdef.fogenabled)
5536 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5537 if (rsurface.texture->colormapping)
5538 permutation |= SHADERPERMUTATION_COLORMAPPING;
5539 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5541 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5542 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5544 if (r_shadow_shadowmapsampler)
5545 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5546 if (r_shadow_shadowmappcf > 1)
5547 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5548 else if (r_shadow_shadowmappcf)
5549 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5551 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5552 permutation |= SHADERPERMUTATION_REFLECTION;
5553 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5554 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5555 if (rsurface.texture->reflectmasktexture)
5556 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5557 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5558 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5559 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5561 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5563 if (r_glsl_offsetmapping.integer)
5565 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5566 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5567 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5568 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5569 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5571 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5572 if (r_glsl_offsetmapping_reliefmapping.integer)
5573 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5576 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5577 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5578 // ambient model lighting
5579 mode = SHADERMODE_LIGHTDIRECTION;
5580 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5581 permutation |= SHADERPERMUTATION_GLOW;
5582 if (r_refdef.fogenabled)
5583 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5584 if (rsurface.texture->colormapping)
5585 permutation |= SHADERPERMUTATION_COLORMAPPING;
5586 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5588 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5589 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5591 if (r_shadow_shadowmapsampler)
5592 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5593 if (r_shadow_shadowmappcf > 1)
5594 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5595 else if (r_shadow_shadowmappcf)
5596 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5598 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5599 permutation |= SHADERPERMUTATION_REFLECTION;
5600 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5601 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5602 if (rsurface.texture->reflectmasktexture)
5603 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5604 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5605 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5606 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5610 if (r_glsl_offsetmapping.integer)
5612 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5613 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5614 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5615 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5616 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5618 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5619 if (r_glsl_offsetmapping_reliefmapping.integer)
5620 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5624 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5626 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5627 permutation |= SHADERPERMUTATION_GLOW;
5628 if (r_refdef.fogenabled)
5629 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5630 if (rsurface.texture->colormapping)
5631 permutation |= SHADERPERMUTATION_COLORMAPPING;
5632 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5634 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5635 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5637 if (r_shadow_shadowmapsampler)
5638 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5639 if (r_shadow_shadowmappcf > 1)
5640 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5641 else if (r_shadow_shadowmappcf)
5642 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5644 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5645 permutation |= SHADERPERMUTATION_REFLECTION;
5646 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5647 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5648 if (rsurface.texture->reflectmasktexture)
5649 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5650 if (FAKELIGHT_ENABLED)
5652 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5653 mode = SHADERMODE_FAKELIGHT;
5654 permutation |= SHADERPERMUTATION_DIFFUSE;
5655 if (specularscale > 0)
5657 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5658 if (r_shadow_glossexact.integer)
5659 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5662 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5664 // deluxemapping (light direction texture)
5665 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5666 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5668 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5669 permutation |= SHADERPERMUTATION_DIFFUSE;
5670 if (specularscale > 0)
5672 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5673 if (r_shadow_glossexact.integer)
5674 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5677 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5679 // fake deluxemapping (uniform light direction in tangentspace)
5680 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5681 permutation |= SHADERPERMUTATION_DIFFUSE;
5682 if (specularscale > 0)
5684 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5685 if (r_shadow_glossexact.integer)
5686 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5689 else if (rsurface.uselightmaptexture)
5691 // ordinary lightmapping (q1bsp, q3bsp)
5692 mode = SHADERMODE_LIGHTMAP;
5696 // ordinary vertex coloring (q3bsp)
5697 mode = SHADERMODE_VERTEXCOLOR;
5699 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5700 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5701 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5704 colormod = dummy_colormod;
5705 switch(vid.renderpath)
5707 case RENDERPATH_D3D9:
5709 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);
5710 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5711 R_SetupShader_SetPermutationHLSL(mode, permutation);
5712 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5713 if (mode == SHADERMODE_LIGHTSOURCE)
5715 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5716 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5720 if (mode == SHADERMODE_LIGHTDIRECTION)
5722 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5725 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5726 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5727 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5728 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5729 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5731 if (mode == SHADERMODE_LIGHTSOURCE)
5733 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5734 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5735 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5736 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5737 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5739 // additive passes are only darkened by fog, not tinted
5740 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5741 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5745 if (mode == SHADERMODE_FLATCOLOR)
5747 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5749 else if (mode == SHADERMODE_LIGHTDIRECTION)
5751 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]);
5752 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5753 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);
5754 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);
5755 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5756 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5757 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5761 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5762 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5763 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);
5764 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);
5765 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5767 // additive passes are only darkened by fog, not tinted
5768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5769 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5771 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5772 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);
5773 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5774 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5775 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5776 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5777 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5778 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5779 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5780 if (mode == SHADERMODE_WATER)
5781 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5783 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5784 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5785 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5786 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5787 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5788 if (rsurface.texture->pantstexture)
5789 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5791 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5792 if (rsurface.texture->shirttexture)
5793 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5795 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5796 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5797 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5798 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5799 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5800 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5801 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5802 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5804 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5805 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5806 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5807 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5808 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5809 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5810 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5811 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5812 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5813 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5814 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5815 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5816 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5817 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5818 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5819 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5820 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5821 if (rsurfacepass == RSURFPASS_BACKGROUND)
5823 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5824 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5825 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5829 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5831 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5832 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5833 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5834 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5835 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5837 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5838 if (rsurface.rtlight)
5840 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5841 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5846 case RENDERPATH_D3D10:
5847 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5849 case RENDERPATH_D3D11:
5850 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5852 case RENDERPATH_GL20:
5853 if (gl_mesh_separatearrays.integer)
5855 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);
5856 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5857 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5858 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5859 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5860 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5861 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5862 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5866 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);
5867 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5869 R_SetupShader_SetPermutationGLSL(mode, permutation);
5870 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5871 if (mode == SHADERMODE_LIGHTSOURCE)
5873 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5874 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5875 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5876 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5877 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5878 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);
5880 // additive passes are only darkened by fog, not tinted
5881 if (r_glsl_permutation->loc_FogColor >= 0)
5882 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5883 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5887 if (mode == SHADERMODE_FLATCOLOR)
5889 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5891 else if (mode == SHADERMODE_LIGHTDIRECTION)
5893 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]);
5894 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]);
5895 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);
5896 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);
5897 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);
5898 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]);
5899 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]);
5903 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]);
5904 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]);
5905 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);
5906 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);
5907 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);
5909 // additive passes are only darkened by fog, not tinted
5910 if (r_glsl_permutation->loc_FogColor >= 0)
5912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5913 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5915 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5917 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);
5918 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]);
5919 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]);
5920 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5921 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5922 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5923 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5924 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5925 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5927 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5928 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5929 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5930 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]);
5931 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]);
5933 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5934 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5935 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5936 if (r_glsl_permutation->loc_Color_Pants >= 0)
5938 if (rsurface.texture->pantstexture)
5939 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5941 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5943 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5945 if (rsurface.texture->shirttexture)
5946 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5948 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5950 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]);
5951 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5952 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5953 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5954 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5955 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]);
5956 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5958 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5959 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5960 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5961 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5962 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5963 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5964 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5965 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5966 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5967 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5968 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5969 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5970 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5971 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5972 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5973 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5974 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5975 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5976 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5977 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5978 if (rsurfacepass == RSURFPASS_BACKGROUND)
5980 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5981 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5982 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5986 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5988 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5989 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5990 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5991 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5992 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5994 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5995 if (rsurface.rtlight)
5997 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5998 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6003 case RENDERPATH_CGGL:
6005 if (gl_mesh_separatearrays.integer)
6007 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);
6008 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6009 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6010 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6011 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6012 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6013 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6014 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6018 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);
6019 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6021 R_SetupShader_SetPermutationCG(mode, permutation);
6022 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6023 if (mode == SHADERMODE_LIGHTSOURCE)
6025 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6026 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6030 if (mode == SHADERMODE_LIGHTDIRECTION)
6032 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
6035 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6036 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6037 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6038 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6039 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
6042 if (mode == SHADERMODE_LIGHTSOURCE)
6044 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6045 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6046 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6047 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6048 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
6050 // additive passes are only darkened by fog, not tinted
6051 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6052 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6056 if (mode == SHADERMODE_FLATCOLOR)
6058 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6060 else if (mode == SHADERMODE_LIGHTDIRECTION)
6062 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
6063 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
6064 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
6065 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
6066 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
6067 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
6068 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
6072 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
6073 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
6074 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
6075 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
6076 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
6078 // additive passes are only darkened by fog, not tinted
6079 if (r_cg_permutation->fp_FogColor)
6081 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6082 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6084 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6087 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
6088 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
6089 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
6090 if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6091 if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6092 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6093 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6094 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6095 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6097 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
6098 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
6099 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6100 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
6101 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6102 if (r_cg_permutation->fp_Color_Pants)
6104 if (rsurface.texture->pantstexture)
6105 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6107 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6110 if (r_cg_permutation->fp_Color_Shirt)
6112 if (rsurface.texture->shirttexture)
6113 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6115 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6118 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
6119 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6120 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6121 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6122 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6123 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
6124 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6126 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6127 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6128 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6129 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6130 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6131 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6132 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6133 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6134 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6135 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6136 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6137 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6138 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6139 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6140 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
6141 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6142 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6143 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6144 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6145 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6146 if (rsurfacepass == RSURFPASS_BACKGROUND)
6148 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
6149 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
6150 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
6154 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
6156 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6157 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6158 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6159 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6160 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6162 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6163 if (rsurface.rtlight)
6165 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6166 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6173 case RENDERPATH_GL13:
6174 case RENDERPATH_GL11:
6179 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6181 // select a permutation of the lighting shader appropriate to this
6182 // combination of texture, entity, light source, and fogging, only use the
6183 // minimum features necessary to avoid wasting rendering time in the
6184 // fragment shader on features that are not being used
6185 unsigned int permutation = 0;
6186 unsigned int mode = 0;
6187 const float *lightcolorbase = rtlight->currentcolor;
6188 float ambientscale = rtlight->ambientscale;
6189 float diffusescale = rtlight->diffusescale;
6190 float specularscale = rtlight->specularscale;
6191 // this is the location of the light in view space
6192 vec3_t viewlightorigin;
6193 // this transforms from view space (camera) to light space (cubemap)
6194 matrix4x4_t viewtolight;
6195 matrix4x4_t lighttoview;
6196 float viewtolight16f[16];
6197 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6199 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6200 if (rtlight->currentcubemap != r_texture_whitecube)
6201 permutation |= SHADERPERMUTATION_CUBEFILTER;
6202 if (diffusescale > 0)
6203 permutation |= SHADERPERMUTATION_DIFFUSE;
6204 if (specularscale > 0)
6206 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6207 if (r_shadow_glossexact.integer)
6208 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6210 if (r_shadow_usingshadowmap2d)
6212 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6213 if (r_shadow_shadowmapvsdct)
6214 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6216 if (r_shadow_shadowmapsampler)
6217 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6218 if (r_shadow_shadowmappcf > 1)
6219 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6220 else if (r_shadow_shadowmappcf)
6221 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6223 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6224 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6225 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6226 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6227 switch(vid.renderpath)
6229 case RENDERPATH_D3D9:
6231 R_SetupShader_SetPermutationHLSL(mode, permutation);
6232 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6233 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6234 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6235 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6236 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6237 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6238 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6239 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6240 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6241 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6243 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6244 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6245 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6246 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6247 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6248 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6251 case RENDERPATH_D3D10:
6252 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6254 case RENDERPATH_D3D11:
6255 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6257 case RENDERPATH_GL20:
6258 R_SetupShader_SetPermutationGLSL(mode, permutation);
6259 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6260 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6261 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);
6262 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);
6263 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);
6264 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]);
6265 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]);
6266 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));
6267 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]);
6268 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6270 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6271 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6272 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6273 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6274 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6275 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6277 case RENDERPATH_CGGL:
6279 R_SetupShader_SetPermutationCG(mode, permutation);
6280 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6281 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6282 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
6283 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
6284 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
6285 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
6286 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
6287 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
6288 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
6289 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6291 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6292 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6293 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6294 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6295 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6296 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6299 case RENDERPATH_GL13:
6300 case RENDERPATH_GL11:
6305 #define SKINFRAME_HASH 1024
6309 int loadsequence; // incremented each level change
6310 memexpandablearray_t array;
6311 skinframe_t *hash[SKINFRAME_HASH];
6314 r_skinframe_t r_skinframe;
6316 void R_SkinFrame_PrepareForPurge(void)
6318 r_skinframe.loadsequence++;
6319 // wrap it without hitting zero
6320 if (r_skinframe.loadsequence >= 200)
6321 r_skinframe.loadsequence = 1;
6324 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6328 // mark the skinframe as used for the purging code
6329 skinframe->loadsequence = r_skinframe.loadsequence;
6332 void R_SkinFrame_Purge(void)
6336 for (i = 0;i < SKINFRAME_HASH;i++)
6338 for (s = r_skinframe.hash[i];s;s = s->next)
6340 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6342 if (s->merged == s->base)
6344 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6345 R_PurgeTexture(s->stain );s->stain = NULL;
6346 R_PurgeTexture(s->merged);s->merged = NULL;
6347 R_PurgeTexture(s->base );s->base = NULL;
6348 R_PurgeTexture(s->pants );s->pants = NULL;
6349 R_PurgeTexture(s->shirt );s->shirt = NULL;
6350 R_PurgeTexture(s->nmap );s->nmap = NULL;
6351 R_PurgeTexture(s->gloss );s->gloss = NULL;
6352 R_PurgeTexture(s->glow );s->glow = NULL;
6353 R_PurgeTexture(s->fog );s->fog = NULL;
6354 R_PurgeTexture(s->reflect);s->reflect = NULL;
6355 s->loadsequence = 0;
6361 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6363 char basename[MAX_QPATH];
6365 Image_StripImageExtension(name, basename, sizeof(basename));
6367 if( last == NULL ) {
6369 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6370 item = r_skinframe.hash[hashindex];
6375 // linearly search through the hash bucket
6376 for( ; item ; item = item->next ) {
6377 if( !strcmp( item->basename, basename ) ) {
6384 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6388 char basename[MAX_QPATH];
6390 Image_StripImageExtension(name, basename, sizeof(basename));
6392 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6393 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6394 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6398 rtexture_t *dyntexture;
6399 // check whether its a dynamic texture
6400 dyntexture = CL_GetDynTexture( basename );
6401 if (!add && !dyntexture)
6403 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6404 memset(item, 0, sizeof(*item));
6405 strlcpy(item->basename, basename, sizeof(item->basename));
6406 item->base = dyntexture; // either NULL or dyntexture handle
6407 item->textureflags = textureflags;
6408 item->comparewidth = comparewidth;
6409 item->compareheight = compareheight;
6410 item->comparecrc = comparecrc;
6411 item->next = r_skinframe.hash[hashindex];
6412 r_skinframe.hash[hashindex] = item;
6414 else if( item->base == NULL )
6416 rtexture_t *dyntexture;
6417 // check whether its a dynamic texture
6418 // 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]
6419 dyntexture = CL_GetDynTexture( basename );
6420 item->base = dyntexture; // either NULL or dyntexture handle
6423 R_SkinFrame_MarkUsed(item);
6427 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6429 unsigned long long avgcolor[5], wsum; \
6437 for(pix = 0; pix < cnt; ++pix) \
6440 for(comp = 0; comp < 3; ++comp) \
6442 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6445 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6447 for(comp = 0; comp < 3; ++comp) \
6448 avgcolor[comp] += getpixel * w; \
6451 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6452 avgcolor[4] += getpixel; \
6454 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6456 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6457 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6458 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6459 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6462 extern cvar_t gl_picmip;
6463 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6466 unsigned char *pixels;
6467 unsigned char *bumppixels;
6468 unsigned char *basepixels = NULL;
6469 int basepixels_width = 0;
6470 int basepixels_height = 0;
6471 skinframe_t *skinframe;
6472 rtexture_t *ddsbase = NULL;
6473 qboolean ddshasalpha = false;
6474 float ddsavgcolor[4];
6475 char basename[MAX_QPATH];
6476 int miplevel = R_PicmipForFlags(textureflags);
6477 int savemiplevel = miplevel;
6480 if (cls.state == ca_dedicated)
6483 // return an existing skinframe if already loaded
6484 // if loading of the first image fails, don't make a new skinframe as it
6485 // would cause all future lookups of this to be missing
6486 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6487 if (skinframe && skinframe->base)
6490 Image_StripImageExtension(name, basename, sizeof(basename));
6492 // check for DDS texture file first
6493 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6495 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6496 if (basepixels == NULL)
6500 // FIXME handle miplevel
6502 if (developer_loading.integer)
6503 Con_Printf("loading skin \"%s\"\n", name);
6505 // we've got some pixels to store, so really allocate this new texture now
6507 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6508 skinframe->stain = NULL;
6509 skinframe->merged = NULL;
6510 skinframe->base = NULL;
6511 skinframe->pants = NULL;
6512 skinframe->shirt = NULL;
6513 skinframe->nmap = NULL;
6514 skinframe->gloss = NULL;
6515 skinframe->glow = NULL;
6516 skinframe->fog = NULL;
6517 skinframe->reflect = NULL;
6518 skinframe->hasalpha = false;
6522 skinframe->base = ddsbase;
6523 skinframe->hasalpha = ddshasalpha;
6524 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6525 if (r_loadfog && skinframe->hasalpha)
6526 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6527 //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]);
6531 basepixels_width = image_width;
6532 basepixels_height = image_height;
6533 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);
6534 if (textureflags & TEXF_ALPHA)
6536 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6538 if (basepixels[j] < 255)
6540 skinframe->hasalpha = true;
6544 if (r_loadfog && skinframe->hasalpha)
6546 // has transparent pixels
6547 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6548 for (j = 0;j < image_width * image_height * 4;j += 4)
6553 pixels[j+3] = basepixels[j+3];
6555 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);
6559 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6560 //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]);
6561 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6562 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6563 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6564 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6569 mymiplevel = savemiplevel;
6570 if (r_loadnormalmap)
6571 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);
6572 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6574 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6576 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6577 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6580 // _norm is the name used by tenebrae and has been adopted as standard
6581 if (r_loadnormalmap && skinframe->nmap == NULL)
6583 mymiplevel = savemiplevel;
6584 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6586 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);
6590 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6592 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6593 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6594 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);
6596 Mem_Free(bumppixels);
6598 else if (r_shadow_bumpscale_basetexture.value > 0)
6600 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6601 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6602 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);
6605 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6606 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6609 // _luma is supported only for tenebrae compatibility
6610 // _glow is the preferred name
6611 mymiplevel = savemiplevel;
6612 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))))
6614 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);
6615 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6616 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6617 Mem_Free(pixels);pixels = NULL;
6620 mymiplevel = savemiplevel;
6621 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6623 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);
6624 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6625 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6630 mymiplevel = savemiplevel;
6631 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6633 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);
6634 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6635 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6640 mymiplevel = savemiplevel;
6641 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6643 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);
6644 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6645 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6650 mymiplevel = savemiplevel;
6651 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6653 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);
6654 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6655 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6661 Mem_Free(basepixels);
6666 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6667 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6670 unsigned char *temp1, *temp2;
6671 skinframe_t *skinframe;
6673 if (cls.state == ca_dedicated)
6676 // if already loaded just return it, otherwise make a new skinframe
6677 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6678 if (skinframe && skinframe->base)
6681 skinframe->stain = NULL;
6682 skinframe->merged = NULL;
6683 skinframe->base = NULL;
6684 skinframe->pants = NULL;
6685 skinframe->shirt = NULL;
6686 skinframe->nmap = NULL;
6687 skinframe->gloss = NULL;
6688 skinframe->glow = NULL;
6689 skinframe->fog = NULL;
6690 skinframe->reflect = NULL;
6691 skinframe->hasalpha = false;
6693 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6697 if (developer_loading.integer)
6698 Con_Printf("loading 32bit skin \"%s\"\n", name);
6700 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6702 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6703 temp2 = temp1 + width * height * 4;
6704 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6705 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);
6708 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6709 if (textureflags & TEXF_ALPHA)
6711 for (i = 3;i < width * height * 4;i += 4)
6713 if (skindata[i] < 255)
6715 skinframe->hasalpha = true;
6719 if (r_loadfog && skinframe->hasalpha)
6721 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6722 memcpy(fogpixels, skindata, width * height * 4);
6723 for (i = 0;i < width * height * 4;i += 4)
6724 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6725 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6726 Mem_Free(fogpixels);
6730 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6731 //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]);
6736 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6740 skinframe_t *skinframe;
6742 if (cls.state == ca_dedicated)
6745 // if already loaded just return it, otherwise make a new skinframe
6746 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6747 if (skinframe && skinframe->base)
6750 skinframe->stain = NULL;
6751 skinframe->merged = NULL;
6752 skinframe->base = NULL;
6753 skinframe->pants = NULL;
6754 skinframe->shirt = NULL;
6755 skinframe->nmap = NULL;
6756 skinframe->gloss = NULL;
6757 skinframe->glow = NULL;
6758 skinframe->fog = NULL;
6759 skinframe->reflect = NULL;
6760 skinframe->hasalpha = false;
6762 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6766 if (developer_loading.integer)
6767 Con_Printf("loading quake skin \"%s\"\n", name);
6769 // 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)
6770 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6771 memcpy(skinframe->qpixels, skindata, width*height);
6772 skinframe->qwidth = width;
6773 skinframe->qheight = height;
6776 for (i = 0;i < width * height;i++)
6777 featuresmask |= palette_featureflags[skindata[i]];
6779 skinframe->hasalpha = false;
6780 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6781 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6782 skinframe->qgeneratemerged = true;
6783 skinframe->qgeneratebase = skinframe->qhascolormapping;
6784 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6786 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6787 //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]);
6792 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6796 unsigned char *skindata;
6798 if (!skinframe->qpixels)
6801 if (!skinframe->qhascolormapping)
6802 colormapped = false;
6806 if (!skinframe->qgeneratebase)
6811 if (!skinframe->qgeneratemerged)
6815 width = skinframe->qwidth;
6816 height = skinframe->qheight;
6817 skindata = skinframe->qpixels;
6819 if (skinframe->qgeneratenmap)
6821 unsigned char *temp1, *temp2;
6822 skinframe->qgeneratenmap = false;
6823 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6824 temp2 = temp1 + width * height * 4;
6825 // use either a custom palette or the quake palette
6826 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6827 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6828 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);
6832 if (skinframe->qgenerateglow)
6834 skinframe->qgenerateglow = false;
6835 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6840 skinframe->qgeneratebase = false;
6841 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);
6842 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6843 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6847 skinframe->qgeneratemerged = false;
6848 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);
6851 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6853 Mem_Free(skinframe->qpixels);
6854 skinframe->qpixels = NULL;
6858 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)
6861 skinframe_t *skinframe;
6863 if (cls.state == ca_dedicated)
6866 // if already loaded just return it, otherwise make a new skinframe
6867 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6868 if (skinframe && skinframe->base)
6871 skinframe->stain = NULL;
6872 skinframe->merged = NULL;
6873 skinframe->base = NULL;
6874 skinframe->pants = NULL;
6875 skinframe->shirt = NULL;
6876 skinframe->nmap = NULL;
6877 skinframe->gloss = NULL;
6878 skinframe->glow = NULL;
6879 skinframe->fog = NULL;
6880 skinframe->reflect = NULL;
6881 skinframe->hasalpha = false;
6883 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6887 if (developer_loading.integer)
6888 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6890 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6891 if (textureflags & TEXF_ALPHA)
6893 for (i = 0;i < width * height;i++)
6895 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6897 skinframe->hasalpha = true;
6901 if (r_loadfog && skinframe->hasalpha)
6902 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6905 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6906 //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]);
6911 skinframe_t *R_SkinFrame_LoadMissing(void)
6913 skinframe_t *skinframe;
6915 if (cls.state == ca_dedicated)
6918 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6919 skinframe->stain = NULL;
6920 skinframe->merged = NULL;
6921 skinframe->base = NULL;
6922 skinframe->pants = NULL;
6923 skinframe->shirt = NULL;
6924 skinframe->nmap = NULL;
6925 skinframe->gloss = NULL;
6926 skinframe->glow = NULL;
6927 skinframe->fog = NULL;
6928 skinframe->reflect = NULL;
6929 skinframe->hasalpha = false;
6931 skinframe->avgcolor[0] = rand() / RAND_MAX;
6932 skinframe->avgcolor[1] = rand() / RAND_MAX;
6933 skinframe->avgcolor[2] = rand() / RAND_MAX;
6934 skinframe->avgcolor[3] = 1;
6939 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6940 typedef struct suffixinfo_s
6943 qboolean flipx, flipy, flipdiagonal;
6946 static suffixinfo_t suffix[3][6] =
6949 {"px", false, false, false},
6950 {"nx", false, false, false},
6951 {"py", false, false, false},
6952 {"ny", false, false, false},
6953 {"pz", false, false, false},
6954 {"nz", false, false, false}
6957 {"posx", false, false, false},
6958 {"negx", false, false, false},
6959 {"posy", false, false, false},
6960 {"negy", false, false, false},
6961 {"posz", false, false, false},
6962 {"negz", false, false, false}
6965 {"rt", true, false, true},
6966 {"lf", false, true, true},
6967 {"ft", true, true, false},
6968 {"bk", false, false, false},
6969 {"up", true, false, true},
6970 {"dn", true, false, true}
6974 static int componentorder[4] = {0, 1, 2, 3};
6976 rtexture_t *R_LoadCubemap(const char *basename)
6978 int i, j, cubemapsize;
6979 unsigned char *cubemappixels, *image_buffer;
6980 rtexture_t *cubemaptexture;
6982 // must start 0 so the first loadimagepixels has no requested width/height
6984 cubemappixels = NULL;
6985 cubemaptexture = NULL;
6986 // keep trying different suffix groups (posx, px, rt) until one loads
6987 for (j = 0;j < 3 && !cubemappixels;j++)
6989 // load the 6 images in the suffix group
6990 for (i = 0;i < 6;i++)
6992 // generate an image name based on the base and and suffix
6993 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6995 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6997 // an image loaded, make sure width and height are equal
6998 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7000 // if this is the first image to load successfully, allocate the cubemap memory
7001 if (!cubemappixels && image_width >= 1)
7003 cubemapsize = image_width;
7004 // note this clears to black, so unavailable sides are black
7005 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7007 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7009 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);
7012 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7014 Mem_Free(image_buffer);
7018 // if a cubemap loaded, upload it
7021 if (developer_loading.integer)
7022 Con_Printf("loading cubemap \"%s\"\n", basename);
7024 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7025 Mem_Free(cubemappixels);
7029 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7030 if (developer_loading.integer)
7032 Con_Printf("(tried tried images ");
7033 for (j = 0;j < 3;j++)
7034 for (i = 0;i < 6;i++)
7035 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7036 Con_Print(" and was unable to find any of them).\n");
7039 return cubemaptexture;
7042 rtexture_t *R_GetCubemap(const char *basename)
7045 for (i = 0;i < r_texture_numcubemaps;i++)
7046 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7047 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7048 if (i >= MAX_CUBEMAPS)
7049 return r_texture_whitecube;
7050 r_texture_numcubemaps++;
7051 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7052 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7053 return r_texture_cubemaps[i].texture;
7056 void R_FreeCubemaps(void)
7059 for (i = 0;i < r_texture_numcubemaps;i++)
7061 if (developer_loading.integer)
7062 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7063 if (r_texture_cubemaps[i].texture)
7064 R_FreeTexture(r_texture_cubemaps[i].texture);
7066 r_texture_numcubemaps = 0;
7069 void R_Main_FreeViewCache(void)
7071 if (r_refdef.viewcache.entityvisible)
7072 Mem_Free(r_refdef.viewcache.entityvisible);
7073 if (r_refdef.viewcache.world_pvsbits)
7074 Mem_Free(r_refdef.viewcache.world_pvsbits);
7075 if (r_refdef.viewcache.world_leafvisible)
7076 Mem_Free(r_refdef.viewcache.world_leafvisible);
7077 if (r_refdef.viewcache.world_surfacevisible)
7078 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7079 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7082 void R_Main_ResizeViewCache(void)
7084 int numentities = r_refdef.scene.numentities;
7085 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7086 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7087 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7088 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7089 if (r_refdef.viewcache.maxentities < numentities)
7091 r_refdef.viewcache.maxentities = numentities;
7092 if (r_refdef.viewcache.entityvisible)
7093 Mem_Free(r_refdef.viewcache.entityvisible);
7094 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7096 if (r_refdef.viewcache.world_numclusters != numclusters)
7098 r_refdef.viewcache.world_numclusters = numclusters;
7099 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7100 if (r_refdef.viewcache.world_pvsbits)
7101 Mem_Free(r_refdef.viewcache.world_pvsbits);
7102 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7104 if (r_refdef.viewcache.world_numleafs != numleafs)
7106 r_refdef.viewcache.world_numleafs = numleafs;
7107 if (r_refdef.viewcache.world_leafvisible)
7108 Mem_Free(r_refdef.viewcache.world_leafvisible);
7109 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7111 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7113 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7114 if (r_refdef.viewcache.world_surfacevisible)
7115 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7116 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7120 extern rtexture_t *loadingscreentexture;
7121 void gl_main_start(void)
7123 loadingscreentexture = NULL;
7124 r_texture_blanknormalmap = NULL;
7125 r_texture_white = NULL;
7126 r_texture_grey128 = NULL;
7127 r_texture_black = NULL;
7128 r_texture_whitecube = NULL;
7129 r_texture_normalizationcube = NULL;
7130 r_texture_fogattenuation = NULL;
7131 r_texture_fogheighttexture = NULL;
7132 r_texture_gammaramps = NULL;
7133 r_texture_numcubemaps = 0;
7135 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7136 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7138 switch(vid.renderpath)
7140 case RENDERPATH_GL20:
7141 case RENDERPATH_CGGL:
7142 case RENDERPATH_D3D9:
7143 case RENDERPATH_D3D10:
7144 case RENDERPATH_D3D11:
7145 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7146 Cvar_SetValueQuick(&gl_combine, 1);
7147 Cvar_SetValueQuick(&r_glsl, 1);
7148 r_loadnormalmap = true;
7152 case RENDERPATH_GL13:
7153 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7154 Cvar_SetValueQuick(&gl_combine, 1);
7155 Cvar_SetValueQuick(&r_glsl, 0);
7156 r_loadnormalmap = false;
7157 r_loadgloss = false;
7160 case RENDERPATH_GL11:
7161 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7162 Cvar_SetValueQuick(&gl_combine, 0);
7163 Cvar_SetValueQuick(&r_glsl, 0);
7164 r_loadnormalmap = false;
7165 r_loadgloss = false;
7171 R_FrameData_Reset();
7175 memset(r_queries, 0, sizeof(r_queries));
7177 r_qwskincache = NULL;
7178 r_qwskincache_size = 0;
7180 // set up r_skinframe loading system for textures
7181 memset(&r_skinframe, 0, sizeof(r_skinframe));
7182 r_skinframe.loadsequence = 1;
7183 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7185 r_main_texturepool = R_AllocTexturePool();
7186 R_BuildBlankTextures();
7188 if (vid.support.arb_texture_cube_map)
7191 R_BuildNormalizationCube();
7193 r_texture_fogattenuation = NULL;
7194 r_texture_fogheighttexture = NULL;
7195 r_texture_gammaramps = NULL;
7196 //r_texture_fogintensity = NULL;
7197 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7198 memset(&r_waterstate, 0, sizeof(r_waterstate));
7199 r_glsl_permutation = NULL;
7200 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7201 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7202 glslshaderstring = NULL;
7204 r_cg_permutation = NULL;
7205 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7206 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7207 cgshaderstring = NULL;
7210 r_hlsl_permutation = NULL;
7211 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7212 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7213 hlslshaderstring = NULL;
7215 memset(&r_svbsp, 0, sizeof (r_svbsp));
7217 r_refdef.fogmasktable_density = 0;
7220 void gl_main_shutdown(void)
7223 R_FrameData_Reset();
7225 R_Main_FreeViewCache();
7227 switch(vid.renderpath)
7229 case RENDERPATH_GL11:
7230 case RENDERPATH_GL13:
7231 case RENDERPATH_GL20:
7232 case RENDERPATH_CGGL:
7234 qglDeleteQueriesARB(r_maxqueries, r_queries);
7236 case RENDERPATH_D3D9:
7237 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7239 case RENDERPATH_D3D10:
7240 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7242 case RENDERPATH_D3D11:
7243 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7249 memset(r_queries, 0, sizeof(r_queries));
7251 r_qwskincache = NULL;
7252 r_qwskincache_size = 0;
7254 // clear out the r_skinframe state
7255 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7256 memset(&r_skinframe, 0, sizeof(r_skinframe));
7259 Mem_Free(r_svbsp.nodes);
7260 memset(&r_svbsp, 0, sizeof (r_svbsp));
7261 R_FreeTexturePool(&r_main_texturepool);
7262 loadingscreentexture = NULL;
7263 r_texture_blanknormalmap = NULL;
7264 r_texture_white = NULL;
7265 r_texture_grey128 = NULL;
7266 r_texture_black = NULL;
7267 r_texture_whitecube = NULL;
7268 r_texture_normalizationcube = NULL;
7269 r_texture_fogattenuation = NULL;
7270 r_texture_fogheighttexture = NULL;
7271 r_texture_gammaramps = NULL;
7272 r_texture_numcubemaps = 0;
7273 //r_texture_fogintensity = NULL;
7274 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7275 memset(&r_waterstate, 0, sizeof(r_waterstate));
7279 extern void CL_ParseEntityLump(char *entitystring);
7280 void gl_main_newmap(void)
7282 // FIXME: move this code to client
7283 char *entities, entname[MAX_QPATH];
7285 Mem_Free(r_qwskincache);
7286 r_qwskincache = NULL;
7287 r_qwskincache_size = 0;
7290 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7291 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7293 CL_ParseEntityLump(entities);
7297 if (cl.worldmodel->brush.entities)
7298 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7300 R_Main_FreeViewCache();
7302 R_FrameData_Reset();
7305 void GL_Main_Init(void)
7307 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7309 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7310 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7311 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7312 if (gamemode == GAME_NEHAHRA)
7314 Cvar_RegisterVariable (&gl_fogenable);
7315 Cvar_RegisterVariable (&gl_fogdensity);
7316 Cvar_RegisterVariable (&gl_fogred);
7317 Cvar_RegisterVariable (&gl_foggreen);
7318 Cvar_RegisterVariable (&gl_fogblue);
7319 Cvar_RegisterVariable (&gl_fogstart);
7320 Cvar_RegisterVariable (&gl_fogend);
7321 Cvar_RegisterVariable (&gl_skyclip);
7323 Cvar_RegisterVariable(&r_motionblur);
7324 Cvar_RegisterVariable(&r_motionblur_maxblur);
7325 Cvar_RegisterVariable(&r_motionblur_bmin);
7326 Cvar_RegisterVariable(&r_motionblur_vmin);
7327 Cvar_RegisterVariable(&r_motionblur_vmax);
7328 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7329 Cvar_RegisterVariable(&r_motionblur_randomize);
7330 Cvar_RegisterVariable(&r_damageblur);
7331 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7332 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7333 Cvar_RegisterVariable(&r_equalize_entities_by);
7334 Cvar_RegisterVariable(&r_equalize_entities_to);
7335 Cvar_RegisterVariable(&r_depthfirst);
7336 Cvar_RegisterVariable(&r_useinfinitefarclip);
7337 Cvar_RegisterVariable(&r_farclip_base);
7338 Cvar_RegisterVariable(&r_farclip_world);
7339 Cvar_RegisterVariable(&r_nearclip);
7340 Cvar_RegisterVariable(&r_showbboxes);
7341 Cvar_RegisterVariable(&r_showsurfaces);
7342 Cvar_RegisterVariable(&r_showtris);
7343 Cvar_RegisterVariable(&r_shownormals);
7344 Cvar_RegisterVariable(&r_showlighting);
7345 Cvar_RegisterVariable(&r_showshadowvolumes);
7346 Cvar_RegisterVariable(&r_showcollisionbrushes);
7347 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7348 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7349 Cvar_RegisterVariable(&r_showdisabledepthtest);
7350 Cvar_RegisterVariable(&r_drawportals);
7351 Cvar_RegisterVariable(&r_drawentities);
7352 Cvar_RegisterVariable(&r_draw2d);
7353 Cvar_RegisterVariable(&r_drawworld);
7354 Cvar_RegisterVariable(&r_cullentities_trace);
7355 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7356 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7357 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7358 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7359 Cvar_RegisterVariable(&r_drawviewmodel);
7360 Cvar_RegisterVariable(&r_drawexteriormodel);
7361 Cvar_RegisterVariable(&r_speeds);
7362 Cvar_RegisterVariable(&r_fullbrights);
7363 Cvar_RegisterVariable(&r_wateralpha);
7364 Cvar_RegisterVariable(&r_dynamic);
7365 Cvar_RegisterVariable(&r_fakelight);
7366 Cvar_RegisterVariable(&r_fakelight_intensity);
7367 Cvar_RegisterVariable(&r_fullbright);
7368 Cvar_RegisterVariable(&r_shadows);
7369 Cvar_RegisterVariable(&r_shadows_darken);
7370 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7371 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7372 Cvar_RegisterVariable(&r_shadows_throwdistance);
7373 Cvar_RegisterVariable(&r_shadows_throwdirection);
7374 Cvar_RegisterVariable(&r_shadows_focus);
7375 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7376 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7377 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7378 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7379 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7380 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7381 Cvar_RegisterVariable(&r_fog_exp2);
7382 Cvar_RegisterVariable(&r_drawfog);
7383 Cvar_RegisterVariable(&r_transparentdepthmasking);
7384 Cvar_RegisterVariable(&r_texture_dds_load);
7385 Cvar_RegisterVariable(&r_texture_dds_save);
7386 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7387 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7388 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7389 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7390 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7391 Cvar_RegisterVariable(&r_textureunits);
7392 Cvar_RegisterVariable(&gl_combine);
7393 Cvar_RegisterVariable(&r_glsl);
7394 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7395 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7396 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7397 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7398 Cvar_RegisterVariable(&r_glsl_postprocess);
7399 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7400 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7401 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7402 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7403 Cvar_RegisterVariable(&r_water);
7404 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7405 Cvar_RegisterVariable(&r_water_clippingplanebias);
7406 Cvar_RegisterVariable(&r_water_refractdistort);
7407 Cvar_RegisterVariable(&r_water_reflectdistort);
7408 Cvar_RegisterVariable(&r_water_scissormode);
7409 Cvar_RegisterVariable(&r_lerpsprites);
7410 Cvar_RegisterVariable(&r_lerpmodels);
7411 Cvar_RegisterVariable(&r_lerplightstyles);
7412 Cvar_RegisterVariable(&r_waterscroll);
7413 Cvar_RegisterVariable(&r_bloom);
7414 Cvar_RegisterVariable(&r_bloom_colorscale);
7415 Cvar_RegisterVariable(&r_bloom_brighten);
7416 Cvar_RegisterVariable(&r_bloom_blur);
7417 Cvar_RegisterVariable(&r_bloom_resolution);
7418 Cvar_RegisterVariable(&r_bloom_colorexponent);
7419 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7420 Cvar_RegisterVariable(&r_hdr);
7421 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7422 Cvar_RegisterVariable(&r_hdr_glowintensity);
7423 Cvar_RegisterVariable(&r_hdr_range);
7424 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7425 Cvar_RegisterVariable(&developer_texturelogging);
7426 Cvar_RegisterVariable(&gl_lightmaps);
7427 Cvar_RegisterVariable(&r_test);
7428 Cvar_RegisterVariable(&r_glsl_saturation);
7429 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7430 Cvar_RegisterVariable(&r_framedatasize);
7431 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7432 Cvar_SetValue("r_fullbrights", 0);
7433 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7435 Cvar_RegisterVariable(&r_track_sprites);
7436 Cvar_RegisterVariable(&r_track_sprites_flags);
7437 Cvar_RegisterVariable(&r_track_sprites_scalew);
7438 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7439 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7440 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7443 extern void R_Textures_Init(void);
7444 extern void GL_Draw_Init(void);
7445 extern void GL_Main_Init(void);
7446 extern void R_Shadow_Init(void);
7447 extern void R_Sky_Init(void);
7448 extern void GL_Surf_Init(void);
7449 extern void R_Particles_Init(void);
7450 extern void R_Explosion_Init(void);
7451 extern void gl_backend_init(void);
7452 extern void Sbar_Init(void);
7453 extern void R_LightningBeams_Init(void);
7454 extern void Mod_RenderInit(void);
7455 extern void Font_Init(void);
7457 void Render_Init(void)
7470 R_LightningBeams_Init();
7479 extern char *ENGINE_EXTENSIONS;
7482 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7483 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7484 gl_version = (const char *)qglGetString(GL_VERSION);
7485 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7489 if (!gl_platformextensions)
7490 gl_platformextensions = "";
7492 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7493 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7494 Con_Printf("GL_VERSION: %s\n", gl_version);
7495 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7496 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7498 VID_CheckExtensions();
7500 // LordHavoc: report supported extensions
7501 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7503 // clear to black (loading plaque will be seen over this)
7504 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7507 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7511 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7513 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7516 p = r_refdef.view.frustum + i;
7521 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7525 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7529 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7533 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7537 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7541 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7545 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7549 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7557 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7561 for (i = 0;i < numplanes;i++)
7568 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7572 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7576 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7580 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7584 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7588 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7592 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7596 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7604 //==================================================================================
7606 // LordHavoc: this stores temporary data used within the same frame
7608 qboolean r_framedata_failed;
7609 static size_t r_framedata_size;
7610 static size_t r_framedata_current;
7611 static void *r_framedata_base;
7613 void R_FrameData_Reset(void)
7615 if (r_framedata_base)
7616 Mem_Free(r_framedata_base);
7617 r_framedata_base = NULL;
7618 r_framedata_size = 0;
7619 r_framedata_current = 0;
7620 r_framedata_failed = false;
7623 void R_FrameData_NewFrame(void)
7626 if (r_framedata_failed)
7627 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7628 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7629 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7630 if (r_framedata_size != wantedsize)
7632 r_framedata_size = wantedsize;
7633 if (r_framedata_base)
7634 Mem_Free(r_framedata_base);
7635 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7637 r_framedata_current = 0;
7638 r_framedata_failed = false;
7641 void *R_FrameData_Alloc(size_t size)
7645 // align to 16 byte boundary
7646 size = (size + 15) & ~15;
7647 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7648 r_framedata_current += size;
7651 if (r_framedata_current > r_framedata_size)
7652 r_framedata_failed = true;
7654 // return NULL on everything after a failure
7655 if (r_framedata_failed)
7661 void *R_FrameData_Store(size_t size, void *data)
7663 void *d = R_FrameData_Alloc(size);
7665 memcpy(d, data, size);
7669 //==================================================================================
7671 // LordHavoc: animcache originally written by Echon, rewritten since then
7674 * Animation cache prevents re-generating mesh data for an animated model
7675 * multiple times in one frame for lighting, shadowing, reflections, etc.
7678 void R_AnimCache_Free(void)
7682 void R_AnimCache_ClearCache(void)
7685 entity_render_t *ent;
7687 for (i = 0;i < r_refdef.scene.numentities;i++)
7689 ent = r_refdef.scene.entities[i];
7690 ent->animcache_vertex3f = NULL;
7691 ent->animcache_normal3f = NULL;
7692 ent->animcache_svector3f = NULL;
7693 ent->animcache_tvector3f = NULL;
7694 ent->animcache_vertexposition = NULL;
7695 ent->animcache_vertexmesh = NULL;
7696 ent->animcache_vertexpositionbuffer = NULL;
7697 ent->animcache_vertexmeshbuffer = NULL;
7701 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7705 // identical memory layout, so no need to allocate...
7706 // this also provides the vertexposition structure to everything, e.g.
7707 // depth masked rendering currently uses it even if having separate
7709 // NOTE: get rid of this optimization if changing it to e.g. 4f
7710 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7713 // get rid of following uses of VERTEXPOSITION, change to the array:
7714 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7715 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7716 // R_DrawTextureSurfaceList_DepthOnly
7717 // R_Q1BSP_DrawShadowMap
7719 switch(vid.renderpath)
7721 case RENDERPATH_GL20:
7722 case RENDERPATH_CGGL:
7723 // need the meshbuffers if !gl_mesh_separatearrays.integer
7724 if (gl_mesh_separatearrays.integer)
7727 case RENDERPATH_D3D9:
7728 case RENDERPATH_D3D10:
7729 case RENDERPATH_D3D11:
7730 // always need the meshbuffers
7732 case RENDERPATH_GL13:
7733 case RENDERPATH_GL11:
7734 // never need the meshbuffers
7738 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7739 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7741 if (!ent->animcache_vertexposition)
7742 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7744 if (ent->animcache_vertexposition)
7747 for (i = 0;i < numvertices;i++)
7748 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7750 // TODO: upload vertex buffer?
7752 if (ent->animcache_vertexmesh)
7754 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7755 for (i = 0;i < numvertices;i++)
7756 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7757 if (ent->animcache_svector3f)
7758 for (i = 0;i < numvertices;i++)
7759 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7760 if (ent->animcache_tvector3f)
7761 for (i = 0;i < numvertices;i++)
7762 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7763 if (ent->animcache_normal3f)
7764 for (i = 0;i < numvertices;i++)
7765 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7766 // TODO: upload vertex buffer?
7770 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7772 dp_model_t *model = ent->model;
7774 // see if it's already cached this frame
7775 if (ent->animcache_vertex3f)
7777 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7778 if (wantnormals || wanttangents)
7780 if (ent->animcache_normal3f)
7781 wantnormals = false;
7782 if (ent->animcache_svector3f)
7783 wanttangents = false;
7784 if (wantnormals || wanttangents)
7786 numvertices = model->surfmesh.num_vertices;
7788 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7791 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7792 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7794 if (!r_framedata_failed)
7796 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7797 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7804 // see if this ent is worth caching
7805 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7807 // get some memory for this entity and generate mesh data
7808 numvertices = model->surfmesh.num_vertices;
7809 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7811 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7814 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7815 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7817 if (!r_framedata_failed)
7819 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7820 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7823 return !r_framedata_failed;
7826 void R_AnimCache_CacheVisibleEntities(void)
7829 qboolean wantnormals = true;
7830 qboolean wanttangents = !r_showsurfaces.integer;
7832 switch(vid.renderpath)
7834 case RENDERPATH_GL20:
7835 case RENDERPATH_CGGL:
7836 case RENDERPATH_D3D9:
7837 case RENDERPATH_D3D10:
7838 case RENDERPATH_D3D11:
7840 case RENDERPATH_GL13:
7841 case RENDERPATH_GL11:
7842 wanttangents = false;
7846 if (r_shownormals.integer)
7847 wanttangents = wantnormals = true;
7849 // TODO: thread this
7850 // NOTE: R_PrepareRTLights() also caches entities
7852 for (i = 0;i < r_refdef.scene.numentities;i++)
7853 if (r_refdef.viewcache.entityvisible[i])
7854 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7857 //==================================================================================
7859 static void R_View_UpdateEntityLighting (void)
7862 entity_render_t *ent;
7863 vec3_t tempdiffusenormal, avg;
7864 vec_t f, fa, fd, fdd;
7865 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7867 for (i = 0;i < r_refdef.scene.numentities;i++)
7869 ent = r_refdef.scene.entities[i];
7871 // skip unseen models
7872 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7876 if (ent->model && ent->model->brush.num_leafs)
7878 // TODO: use modellight for r_ambient settings on world?
7879 VectorSet(ent->modellight_ambient, 0, 0, 0);
7880 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7881 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7885 // fetch the lighting from the worldmodel data
7886 VectorClear(ent->modellight_ambient);
7887 VectorClear(ent->modellight_diffuse);
7888 VectorClear(tempdiffusenormal);
7889 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7892 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7893 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7894 if(ent->flags & RENDER_EQUALIZE)
7896 // first fix up ambient lighting...
7897 if(r_equalize_entities_minambient.value > 0)
7899 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7902 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7903 if(fa < r_equalize_entities_minambient.value * fd)
7906 // fa'/fd' = minambient
7907 // fa'+0.25*fd' = fa+0.25*fd
7909 // fa' = fd' * minambient
7910 // fd'*(0.25+minambient) = fa+0.25*fd
7912 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7913 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7915 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7916 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
7917 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7918 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7923 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7925 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7926 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7929 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7930 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7931 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7937 VectorSet(ent->modellight_ambient, 1, 1, 1);
7939 // move the light direction into modelspace coordinates for lighting code
7940 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7941 if(VectorLength2(ent->modellight_lightdir) == 0)
7942 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7943 VectorNormalize(ent->modellight_lightdir);
7947 #define MAX_LINEOFSIGHTTRACES 64
7949 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7952 vec3_t boxmins, boxmaxs;
7955 dp_model_t *model = r_refdef.scene.worldmodel;
7957 if (!model || !model->brush.TraceLineOfSight)
7960 // expand the box a little
7961 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7962 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7963 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7964 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7965 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7966 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7968 // return true if eye is inside enlarged box
7969 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7973 VectorCopy(eye, start);
7974 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7975 if (model->brush.TraceLineOfSight(model, start, end))
7978 // try various random positions
7979 for (i = 0;i < numsamples;i++)
7981 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7982 if (model->brush.TraceLineOfSight(model, start, end))
7990 static void R_View_UpdateEntityVisible (void)
7995 entity_render_t *ent;
7997 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7998 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7999 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
8000 : RENDER_EXTERIORMODEL;
8001 if (!r_drawviewmodel.integer)
8002 renderimask |= RENDER_VIEWMODEL;
8003 if (!r_drawexteriormodel.integer)
8004 renderimask |= RENDER_EXTERIORMODEL;
8005 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8007 // worldmodel can check visibility
8008 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8009 for (i = 0;i < r_refdef.scene.numentities;i++)
8011 ent = r_refdef.scene.entities[i];
8012 if (!(ent->flags & renderimask))
8013 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)))
8014 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))
8015 r_refdef.viewcache.entityvisible[i] = true;
8017 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8018 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8020 for (i = 0;i < r_refdef.scene.numentities;i++)
8022 ent = r_refdef.scene.entities[i];
8023 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8025 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8027 continue; // temp entities do pvs only
8028 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8029 ent->last_trace_visibility = realtime;
8030 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8031 r_refdef.viewcache.entityvisible[i] = 0;
8038 // no worldmodel or it can't check visibility
8039 for (i = 0;i < r_refdef.scene.numentities;i++)
8041 ent = r_refdef.scene.entities[i];
8042 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));
8047 /// only used if skyrendermasked, and normally returns false
8048 int R_DrawBrushModelsSky (void)
8051 entity_render_t *ent;
8054 for (i = 0;i < r_refdef.scene.numentities;i++)
8056 if (!r_refdef.viewcache.entityvisible[i])
8058 ent = r_refdef.scene.entities[i];
8059 if (!ent->model || !ent->model->DrawSky)
8061 ent->model->DrawSky(ent);
8067 static void R_DrawNoModel(entity_render_t *ent);
8068 static void R_DrawModels(void)
8071 entity_render_t *ent;
8073 for (i = 0;i < r_refdef.scene.numentities;i++)
8075 if (!r_refdef.viewcache.entityvisible[i])
8077 ent = r_refdef.scene.entities[i];
8078 r_refdef.stats.entities++;
8079 if (ent->model && ent->model->Draw != NULL)
8080 ent->model->Draw(ent);
8086 static void R_DrawModelsDepth(void)
8089 entity_render_t *ent;
8091 for (i = 0;i < r_refdef.scene.numentities;i++)
8093 if (!r_refdef.viewcache.entityvisible[i])
8095 ent = r_refdef.scene.entities[i];
8096 if (ent->model && ent->model->DrawDepth != NULL)
8097 ent->model->DrawDepth(ent);
8101 static void R_DrawModelsDebug(void)
8104 entity_render_t *ent;
8106 for (i = 0;i < r_refdef.scene.numentities;i++)
8108 if (!r_refdef.viewcache.entityvisible[i])
8110 ent = r_refdef.scene.entities[i];
8111 if (ent->model && ent->model->DrawDebug != NULL)
8112 ent->model->DrawDebug(ent);
8116 static void R_DrawModelsAddWaterPlanes(void)
8119 entity_render_t *ent;
8121 for (i = 0;i < r_refdef.scene.numentities;i++)
8123 if (!r_refdef.viewcache.entityvisible[i])
8125 ent = r_refdef.scene.entities[i];
8126 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8127 ent->model->DrawAddWaterPlanes(ent);
8131 static void R_View_SetFrustum(const int *scissor)
8134 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8135 vec3_t forward, left, up, origin, v;
8139 // flipped x coordinates (because x points left here)
8140 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8141 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8143 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8144 switch(vid.renderpath)
8146 case RENDERPATH_D3D9:
8147 case RENDERPATH_D3D10:
8148 case RENDERPATH_D3D11:
8149 // non-flipped y coordinates
8150 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8151 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8153 case RENDERPATH_GL11:
8154 case RENDERPATH_GL13:
8155 case RENDERPATH_GL20:
8156 case RENDERPATH_CGGL:
8157 // non-flipped y coordinates
8158 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8159 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8164 // we can't trust r_refdef.view.forward and friends in reflected scenes
8165 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8168 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8169 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8170 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8171 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8172 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8173 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8174 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8175 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8176 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8177 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8178 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8179 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8183 zNear = r_refdef.nearclip;
8184 nudge = 1.0 - 1.0 / (1<<23);
8185 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8186 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8187 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8188 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8189 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8190 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8191 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8192 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8198 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8199 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8200 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8201 r_refdef.view.frustum[0].dist = m[15] - m[12];
8203 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8204 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8205 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8206 r_refdef.view.frustum[1].dist = m[15] + m[12];
8208 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8209 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8210 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8211 r_refdef.view.frustum[2].dist = m[15] - m[13];
8213 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8214 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8215 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8216 r_refdef.view.frustum[3].dist = m[15] + m[13];
8218 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8219 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8220 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8221 r_refdef.view.frustum[4].dist = m[15] - m[14];
8223 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8224 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8225 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8226 r_refdef.view.frustum[5].dist = m[15] + m[14];
8229 if (r_refdef.view.useperspective)
8231 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8232 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8233 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8234 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8235 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8237 // then the normals from the corners relative to origin
8238 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8239 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8240 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8241 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8243 // in a NORMAL view, forward cross left == up
8244 // in a REFLECTED view, forward cross left == down
8245 // so our cross products above need to be adjusted for a left handed coordinate system
8246 CrossProduct(forward, left, v);
8247 if(DotProduct(v, up) < 0)
8249 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8250 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8251 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8252 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8255 // Leaving those out was a mistake, those were in the old code, and they
8256 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8257 // I couldn't reproduce it after adding those normalizations. --blub
8258 VectorNormalize(r_refdef.view.frustum[0].normal);
8259 VectorNormalize(r_refdef.view.frustum[1].normal);
8260 VectorNormalize(r_refdef.view.frustum[2].normal);
8261 VectorNormalize(r_refdef.view.frustum[3].normal);
8263 // make the corners absolute
8264 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8265 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8266 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8267 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8270 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8272 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8273 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8274 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8275 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8276 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8280 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8281 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8282 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8283 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8284 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8285 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8286 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8287 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8288 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8289 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8291 r_refdef.view.numfrustumplanes = 5;
8293 if (r_refdef.view.useclipplane)
8295 r_refdef.view.numfrustumplanes = 6;
8296 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8299 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8300 PlaneClassify(r_refdef.view.frustum + i);
8302 // LordHavoc: note to all quake engine coders, Quake had a special case
8303 // for 90 degrees which assumed a square view (wrong), so I removed it,
8304 // Quake2 has it disabled as well.
8306 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8307 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8308 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8309 //PlaneClassify(&frustum[0]);
8311 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8312 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8313 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8314 //PlaneClassify(&frustum[1]);
8316 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8317 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8318 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8319 //PlaneClassify(&frustum[2]);
8321 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8322 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8323 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8324 //PlaneClassify(&frustum[3]);
8327 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8328 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8329 //PlaneClassify(&frustum[4]);
8332 void R_View_UpdateWithScissor(const int *myscissor)
8334 R_Main_ResizeViewCache();
8335 R_View_SetFrustum(myscissor);
8336 R_View_WorldVisibility(r_refdef.view.useclipplane);
8337 R_View_UpdateEntityVisible();
8338 R_View_UpdateEntityLighting();
8341 void R_View_Update(void)
8343 R_Main_ResizeViewCache();
8344 R_View_SetFrustum(NULL);
8345 R_View_WorldVisibility(r_refdef.view.useclipplane);
8346 R_View_UpdateEntityVisible();
8347 R_View_UpdateEntityLighting();
8350 void R_SetupView(qboolean allowwaterclippingplane)
8352 const float *customclipplane = NULL;
8354 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8356 // LordHavoc: couldn't figure out how to make this approach the
8357 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8358 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8359 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8360 dist = r_refdef.view.clipplane.dist;
8361 plane[0] = r_refdef.view.clipplane.normal[0];
8362 plane[1] = r_refdef.view.clipplane.normal[1];
8363 plane[2] = r_refdef.view.clipplane.normal[2];
8365 customclipplane = plane;
8368 if (!r_refdef.view.useperspective)
8369 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);
8370 else if (vid.stencil && r_useinfinitefarclip.integer)
8371 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);
8373 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);
8374 R_SetViewport(&r_refdef.view.viewport);
8377 void R_EntityMatrix(const matrix4x4_t *matrix)
8379 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8381 gl_modelmatrixchanged = false;
8382 gl_modelmatrix = *matrix;
8383 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8384 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8385 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8386 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8388 switch(vid.renderpath)
8390 case RENDERPATH_D3D9:
8392 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8393 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8396 case RENDERPATH_D3D10:
8397 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8399 case RENDERPATH_D3D11:
8400 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8402 case RENDERPATH_GL20:
8403 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8404 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8405 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8407 case RENDERPATH_CGGL:
8410 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8411 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8412 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8415 case RENDERPATH_GL13:
8416 case RENDERPATH_GL11:
8417 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8423 void R_ResetViewRendering2D(void)
8425 r_viewport_t viewport;
8428 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8429 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);
8430 R_SetViewport(&viewport);
8431 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8432 GL_Color(1, 1, 1, 1);
8433 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8434 GL_BlendFunc(GL_ONE, GL_ZERO);
8435 GL_AlphaTest(false);
8436 GL_ScissorTest(false);
8437 GL_DepthMask(false);
8438 GL_DepthRange(0, 1);
8439 GL_DepthTest(false);
8440 GL_DepthFunc(GL_LEQUAL);
8441 R_EntityMatrix(&identitymatrix);
8442 R_Mesh_ResetTextureState();
8443 GL_PolygonOffset(0, 0);
8444 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8445 switch(vid.renderpath)
8447 case RENDERPATH_GL11:
8448 case RENDERPATH_GL13:
8449 case RENDERPATH_GL20:
8450 case RENDERPATH_CGGL:
8451 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8453 case RENDERPATH_D3D9:
8454 case RENDERPATH_D3D10:
8455 case RENDERPATH_D3D11:
8458 GL_CullFace(GL_NONE);
8461 void R_ResetViewRendering3D(void)
8466 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8467 GL_Color(1, 1, 1, 1);
8468 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8469 GL_BlendFunc(GL_ONE, GL_ZERO);
8470 GL_AlphaTest(false);
8471 GL_ScissorTest(true);
8473 GL_DepthRange(0, 1);
8475 GL_DepthFunc(GL_LEQUAL);
8476 R_EntityMatrix(&identitymatrix);
8477 R_Mesh_ResetTextureState();
8478 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8479 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8480 switch(vid.renderpath)
8482 case RENDERPATH_GL11:
8483 case RENDERPATH_GL13:
8484 case RENDERPATH_GL20:
8485 case RENDERPATH_CGGL:
8486 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8488 case RENDERPATH_D3D9:
8489 case RENDERPATH_D3D10:
8490 case RENDERPATH_D3D11:
8493 GL_CullFace(r_refdef.view.cullface_back);
8498 R_RenderView_UpdateViewVectors
8501 static void R_RenderView_UpdateViewVectors(void)
8503 // break apart the view matrix into vectors for various purposes
8504 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8505 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8506 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8507 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8508 // make an inverted copy of the view matrix for tracking sprites
8509 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8512 void R_RenderScene(void);
8513 void R_RenderWaterPlanes(void);
8515 static void R_Water_StartFrame(void)
8518 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8519 r_waterstate_waterplane_t *p;
8521 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8524 switch(vid.renderpath)
8526 case RENDERPATH_GL20:
8527 case RENDERPATH_CGGL:
8528 case RENDERPATH_D3D9:
8529 case RENDERPATH_D3D10:
8530 case RENDERPATH_D3D11:
8532 case RENDERPATH_GL13:
8533 case RENDERPATH_GL11:
8537 // set waterwidth and waterheight to the water resolution that will be
8538 // used (often less than the screen resolution for faster rendering)
8539 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8540 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8542 // calculate desired texture sizes
8543 // can't use water if the card does not support the texture size
8544 if (!r_water.integer || r_showsurfaces.integer)
8545 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8546 else if (vid.support.arb_texture_non_power_of_two)
8548 texturewidth = waterwidth;
8549 textureheight = waterheight;
8550 camerawidth = waterwidth;
8551 cameraheight = waterheight;
8555 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8556 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8557 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8558 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8561 // allocate textures as needed
8562 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8564 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8565 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8567 if (p->texture_refraction)
8568 R_FreeTexture(p->texture_refraction);
8569 p->texture_refraction = NULL;
8570 if (p->texture_reflection)
8571 R_FreeTexture(p->texture_reflection);
8572 p->texture_reflection = NULL;
8573 if (p->texture_camera)
8574 R_FreeTexture(p->texture_camera);
8575 p->texture_camera = NULL;
8577 memset(&r_waterstate, 0, sizeof(r_waterstate));
8578 r_waterstate.texturewidth = texturewidth;
8579 r_waterstate.textureheight = textureheight;
8580 r_waterstate.camerawidth = camerawidth;
8581 r_waterstate.cameraheight = cameraheight;
8584 if (r_waterstate.texturewidth)
8586 r_waterstate.enabled = true;
8588 // when doing a reduced render (HDR) we want to use a smaller area
8589 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8590 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8592 // set up variables that will be used in shader setup
8593 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8594 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8595 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8596 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8599 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8600 r_waterstate.numwaterplanes = 0;
8603 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8605 int triangleindex, planeindex;
8611 r_waterstate_waterplane_t *p;
8612 texture_t *t = R_GetCurrentTexture(surface->texture);
8614 // just use the first triangle with a valid normal for any decisions
8615 VectorClear(normal);
8616 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8618 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8619 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8620 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8621 TriangleNormal(vert[0], vert[1], vert[2], normal);
8622 if (VectorLength2(normal) >= 0.001)
8626 VectorCopy(normal, plane.normal);
8627 VectorNormalize(plane.normal);
8628 plane.dist = DotProduct(vert[0], plane.normal);
8629 PlaneClassify(&plane);
8630 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8632 // skip backfaces (except if nocullface is set)
8633 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8635 VectorNegate(plane.normal, plane.normal);
8637 PlaneClassify(&plane);
8641 // find a matching plane if there is one
8642 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8643 if(p->camera_entity == t->camera_entity)
8644 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8646 if (planeindex >= r_waterstate.maxwaterplanes)
8647 return; // nothing we can do, out of planes
8649 // if this triangle does not fit any known plane rendered this frame, add one
8650 if (planeindex >= r_waterstate.numwaterplanes)
8652 // store the new plane
8653 r_waterstate.numwaterplanes++;
8655 // clear materialflags and pvs
8656 p->materialflags = 0;
8657 p->pvsvalid = false;
8658 p->camera_entity = t->camera_entity;
8659 VectorCopy(surface->mins, p->mins);
8660 VectorCopy(surface->maxs, p->maxs);
8665 p->mins[0] = min(p->mins[0], surface->mins[0]);
8666 p->mins[1] = min(p->mins[1], surface->mins[1]);
8667 p->mins[2] = min(p->mins[2], surface->mins[2]);
8668 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8669 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8670 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8672 // merge this surface's materialflags into the waterplane
8673 p->materialflags |= t->currentmaterialflags;
8674 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8676 // merge this surface's PVS into the waterplane
8677 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8678 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8679 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8681 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8687 static void R_Water_ProcessPlanes(void)
8690 r_refdef_view_t originalview;
8691 r_refdef_view_t myview;
8693 r_waterstate_waterplane_t *p;
8696 originalview = r_refdef.view;
8698 // make sure enough textures are allocated
8699 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8701 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8703 if (!p->texture_refraction)
8704 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);
8705 if (!p->texture_refraction)
8708 else if (p->materialflags & MATERIALFLAG_CAMERA)
8710 if (!p->texture_camera)
8711 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);
8712 if (!p->texture_camera)
8716 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8718 if (!p->texture_reflection)
8719 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);
8720 if (!p->texture_reflection)
8726 r_refdef.view = originalview;
8727 r_refdef.view.showdebug = false;
8728 r_refdef.view.width = r_waterstate.waterwidth;
8729 r_refdef.view.height = r_waterstate.waterheight;
8730 r_refdef.view.useclipplane = true;
8731 myview = r_refdef.view;
8732 r_waterstate.renderingscene = true;
8733 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8735 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8737 r_refdef.view = myview;
8738 if(r_water_scissormode.integer)
8741 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8742 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8745 // render reflected scene and copy into texture
8746 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8747 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8748 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8749 r_refdef.view.clipplane = p->plane;
8751 // reverse the cullface settings for this render
8752 r_refdef.view.cullface_front = GL_FRONT;
8753 r_refdef.view.cullface_back = GL_BACK;
8754 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8756 r_refdef.view.usecustompvs = true;
8758 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8760 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8763 R_ResetViewRendering3D();
8764 R_ClearScreen(r_refdef.fogenabled);
8765 if(r_water_scissormode.integer & 2)
8766 R_View_UpdateWithScissor(myscissor);
8769 if(r_water_scissormode.integer & 1)
8770 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8773 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);
8776 // render the normal view scene and copy into texture
8777 // (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)
8778 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8780 r_refdef.view = myview;
8781 if(r_water_scissormode.integer)
8784 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8785 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8788 r_waterstate.renderingrefraction = true;
8790 r_refdef.view.clipplane = p->plane;
8791 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8792 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8794 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8796 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8797 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8798 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8799 R_RenderView_UpdateViewVectors();
8800 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8802 r_refdef.view.usecustompvs = true;
8803 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);
8807 PlaneClassify(&r_refdef.view.clipplane);
8809 R_ResetViewRendering3D();
8810 R_ClearScreen(r_refdef.fogenabled);
8811 if(r_water_scissormode.integer & 2)
8812 R_View_UpdateWithScissor(myscissor);
8815 if(r_water_scissormode.integer & 1)
8816 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8819 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);
8820 r_waterstate.renderingrefraction = false;
8822 else if (p->materialflags & MATERIALFLAG_CAMERA)
8824 r_refdef.view = myview;
8826 r_refdef.view.clipplane = p->plane;
8827 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8828 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8830 r_refdef.view.width = r_waterstate.camerawidth;
8831 r_refdef.view.height = r_waterstate.cameraheight;
8832 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8833 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8835 if(p->camera_entity)
8837 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8838 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8841 // note: all of the view is used for displaying... so
8842 // there is no use in scissoring
8844 // reverse the cullface settings for this render
8845 r_refdef.view.cullface_front = GL_FRONT;
8846 r_refdef.view.cullface_back = GL_BACK;
8847 // also reverse the view matrix
8848 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
8849 R_RenderView_UpdateViewVectors();
8850 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8852 r_refdef.view.usecustompvs = true;
8853 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);
8856 // camera needs no clipplane
8857 r_refdef.view.useclipplane = false;
8859 PlaneClassify(&r_refdef.view.clipplane);
8861 R_ResetViewRendering3D();
8862 R_ClearScreen(r_refdef.fogenabled);
8866 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);
8867 r_waterstate.renderingrefraction = false;
8871 r_waterstate.renderingscene = false;
8872 r_refdef.view = originalview;
8873 R_ResetViewRendering3D();
8874 R_ClearScreen(r_refdef.fogenabled);
8878 r_refdef.view = originalview;
8879 r_waterstate.renderingscene = false;
8880 Cvar_SetValueQuick(&r_water, 0);
8881 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8885 void R_Bloom_StartFrame(void)
8887 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8889 switch(vid.renderpath)
8891 case RENDERPATH_GL20:
8892 case RENDERPATH_CGGL:
8893 case RENDERPATH_D3D9:
8894 case RENDERPATH_D3D10:
8895 case RENDERPATH_D3D11:
8897 case RENDERPATH_GL13:
8898 case RENDERPATH_GL11:
8902 // set bloomwidth and bloomheight to the bloom resolution that will be
8903 // used (often less than the screen resolution for faster rendering)
8904 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8905 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8906 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8907 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8908 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8910 // calculate desired texture sizes
8911 if (vid.support.arb_texture_non_power_of_two)
8913 screentexturewidth = r_refdef.view.width;
8914 screentextureheight = r_refdef.view.height;
8915 bloomtexturewidth = r_bloomstate.bloomwidth;
8916 bloomtextureheight = r_bloomstate.bloomheight;
8920 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8921 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8922 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8923 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8926 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))
8928 Cvar_SetValueQuick(&r_hdr, 0);
8929 Cvar_SetValueQuick(&r_bloom, 0);
8930 Cvar_SetValueQuick(&r_motionblur, 0);
8931 Cvar_SetValueQuick(&r_damageblur, 0);
8934 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)))
8935 screentexturewidth = screentextureheight = 0;
8936 if (!r_hdr.integer && !r_bloom.integer)
8937 bloomtexturewidth = bloomtextureheight = 0;
8939 // allocate textures as needed
8940 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8942 if (r_bloomstate.texture_screen)
8943 R_FreeTexture(r_bloomstate.texture_screen);
8944 r_bloomstate.texture_screen = NULL;
8945 r_bloomstate.screentexturewidth = screentexturewidth;
8946 r_bloomstate.screentextureheight = screentextureheight;
8947 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8948 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);
8950 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8952 if (r_bloomstate.texture_bloom)
8953 R_FreeTexture(r_bloomstate.texture_bloom);
8954 r_bloomstate.texture_bloom = NULL;
8955 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8956 r_bloomstate.bloomtextureheight = bloomtextureheight;
8957 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8958 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);
8961 // when doing a reduced render (HDR) we want to use a smaller area
8962 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8963 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8964 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8965 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8966 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8968 // set up a texcoord array for the full resolution screen image
8969 // (we have to keep this around to copy back during final render)
8970 r_bloomstate.screentexcoord2f[0] = 0;
8971 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8972 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8973 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8974 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8975 r_bloomstate.screentexcoord2f[5] = 0;
8976 r_bloomstate.screentexcoord2f[6] = 0;
8977 r_bloomstate.screentexcoord2f[7] = 0;
8979 // set up a texcoord array for the reduced resolution bloom image
8980 // (which will be additive blended over the screen image)
8981 r_bloomstate.bloomtexcoord2f[0] = 0;
8982 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8983 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8984 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8985 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8986 r_bloomstate.bloomtexcoord2f[5] = 0;
8987 r_bloomstate.bloomtexcoord2f[6] = 0;
8988 r_bloomstate.bloomtexcoord2f[7] = 0;
8990 switch(vid.renderpath)
8992 case RENDERPATH_GL11:
8993 case RENDERPATH_GL13:
8994 case RENDERPATH_GL20:
8995 case RENDERPATH_CGGL:
8997 case RENDERPATH_D3D9:
8998 case RENDERPATH_D3D10:
8999 case RENDERPATH_D3D11:
9002 for (i = 0;i < 4;i++)
9004 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9005 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9006 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9007 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9013 if (r_hdr.integer || r_bloom.integer)
9015 r_bloomstate.enabled = true;
9016 r_bloomstate.hdr = r_hdr.integer != 0;
9019 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);
9022 void R_Bloom_CopyBloomTexture(float colorscale)
9024 r_refdef.stats.bloom++;
9026 // scale down screen texture to the bloom texture size
9028 R_SetViewport(&r_bloomstate.viewport);
9029 GL_BlendFunc(GL_ONE, GL_ZERO);
9030 GL_Color(colorscale, colorscale, colorscale, 1);
9031 // 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...
9032 switch(vid.renderpath)
9034 case RENDERPATH_GL11:
9035 case RENDERPATH_GL13:
9036 case RENDERPATH_GL20:
9037 case RENDERPATH_CGGL:
9038 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9040 case RENDERPATH_D3D9:
9041 case RENDERPATH_D3D10:
9042 case RENDERPATH_D3D11:
9043 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9046 // TODO: do boxfilter scale-down in shader?
9047 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9048 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9049 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9051 // we now have a bloom image in the framebuffer
9052 // copy it into the bloom image texture for later processing
9053 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);
9054 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9057 void R_Bloom_CopyHDRTexture(void)
9059 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);
9060 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9063 void R_Bloom_MakeTexture(void)
9066 float xoffset, yoffset, r, brighten;
9068 r_refdef.stats.bloom++;
9070 R_ResetViewRendering2D();
9072 // we have a bloom image in the framebuffer
9074 R_SetViewport(&r_bloomstate.viewport);
9076 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9079 r = bound(0, r_bloom_colorexponent.value / x, 1);
9080 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9082 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9083 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9084 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9085 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9087 // copy the vertically blurred bloom view to a texture
9088 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);
9089 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9092 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9093 brighten = r_bloom_brighten.value;
9095 brighten *= r_hdr_range.value;
9096 brighten = sqrt(brighten);
9098 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9099 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9101 for (dir = 0;dir < 2;dir++)
9103 // blend on at multiple vertical offsets to achieve a vertical blur
9104 // TODO: do offset blends using GLSL
9105 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9106 GL_BlendFunc(GL_ONE, GL_ZERO);
9107 for (x = -range;x <= range;x++)
9109 if (!dir){xoffset = 0;yoffset = x;}
9110 else {xoffset = x;yoffset = 0;}
9111 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9112 yoffset /= (float)r_bloomstate.bloomtextureheight;
9113 // compute a texcoord array with the specified x and y offset
9114 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9115 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9116 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9117 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9118 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9119 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9120 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9121 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9122 // this r value looks like a 'dot' particle, fading sharply to
9123 // black at the edges
9124 // (probably not realistic but looks good enough)
9125 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9126 //r = brighten/(range*2+1);
9127 r = brighten / (range * 2 + 1);
9129 r *= (1 - x*x/(float)(range*range));
9130 GL_Color(r, r, r, 1);
9131 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9132 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9133 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9134 GL_BlendFunc(GL_ONE, GL_ONE);
9137 // copy the vertically blurred bloom view to a texture
9138 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);
9139 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9143 void R_HDR_RenderBloomTexture(void)
9145 int oldwidth, oldheight;
9146 float oldcolorscale;
9148 oldcolorscale = r_refdef.view.colorscale;
9149 oldwidth = r_refdef.view.width;
9150 oldheight = r_refdef.view.height;
9151 r_refdef.view.width = r_bloomstate.bloomwidth;
9152 r_refdef.view.height = r_bloomstate.bloomheight;
9154 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9155 // TODO: add exposure compensation features
9156 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9158 r_refdef.view.showdebug = false;
9159 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9161 R_ResetViewRendering3D();
9163 R_ClearScreen(r_refdef.fogenabled);
9164 if (r_timereport_active)
9165 R_TimeReport("HDRclear");
9168 if (r_timereport_active)
9169 R_TimeReport("visibility");
9171 // only do secondary renders with HDR if r_hdr is 2 or higher
9172 r_waterstate.numwaterplanes = 0;
9173 if (r_waterstate.enabled && r_hdr.integer >= 2)
9174 R_RenderWaterPlanes();
9176 r_refdef.view.showdebug = true;
9178 r_waterstate.numwaterplanes = 0;
9180 R_ResetViewRendering2D();
9182 R_Bloom_CopyHDRTexture();
9183 R_Bloom_MakeTexture();
9185 // restore the view settings
9186 r_refdef.view.width = oldwidth;
9187 r_refdef.view.height = oldheight;
9188 r_refdef.view.colorscale = oldcolorscale;
9190 R_ResetViewRendering3D();
9192 R_ClearScreen(r_refdef.fogenabled);
9193 if (r_timereport_active)
9194 R_TimeReport("viewclear");
9197 static void R_BlendView(void)
9199 unsigned int permutation;
9200 float uservecs[4][4];
9202 switch (vid.renderpath)
9204 case RENDERPATH_GL20:
9205 case RENDERPATH_CGGL:
9206 case RENDERPATH_D3D9:
9207 case RENDERPATH_D3D10:
9208 case RENDERPATH_D3D11:
9210 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9211 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9212 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9213 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9214 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9216 if (r_bloomstate.texture_screen)
9218 // make sure the buffer is available
9219 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9221 R_ResetViewRendering2D();
9223 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9225 // declare variables
9227 static float avgspeed;
9229 speed = VectorLength(cl.movement_velocity);
9231 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9232 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9234 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9235 speed = bound(0, speed, 1);
9236 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9238 // calculate values into a standard alpha
9239 cl.motionbluralpha = 1 - exp(-
9241 (r_motionblur.value * speed / 80)
9243 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9246 max(0.0001, cl.time - cl.oldtime) // fps independent
9249 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9250 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9252 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9254 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9255 GL_Color(1, 1, 1, cl.motionbluralpha);
9256 switch(vid.renderpath)
9258 case RENDERPATH_GL11:
9259 case RENDERPATH_GL13:
9260 case RENDERPATH_GL20:
9261 case RENDERPATH_CGGL:
9262 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9264 case RENDERPATH_D3D9:
9265 case RENDERPATH_D3D10:
9266 case RENDERPATH_D3D11:
9267 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9270 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9271 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9272 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9276 // copy view into the screen texture
9277 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);
9278 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9280 else if (!r_bloomstate.texture_bloom)
9282 // we may still have to do view tint...
9283 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9285 // apply a color tint to the whole view
9286 R_ResetViewRendering2D();
9287 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9288 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9289 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9290 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9291 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9293 break; // no screen processing, no bloom, skip it
9296 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9298 // render simple bloom effect
9299 // copy the screen and shrink it and darken it for the bloom process
9300 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9301 // make the bloom texture
9302 R_Bloom_MakeTexture();
9305 #if _MSC_VER >= 1400
9306 #define sscanf sscanf_s
9308 memset(uservecs, 0, sizeof(uservecs));
9309 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9310 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9311 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9312 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9314 R_ResetViewRendering2D();
9315 GL_Color(1, 1, 1, 1);
9316 GL_BlendFunc(GL_ONE, GL_ZERO);
9318 switch(vid.renderpath)
9320 case RENDERPATH_GL20:
9321 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9322 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9323 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9324 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9325 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9326 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]);
9327 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9328 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]);
9329 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]);
9330 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]);
9331 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]);
9332 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9333 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9334 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);
9336 case RENDERPATH_CGGL:
9338 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9339 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9340 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9341 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9342 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9343 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
9344 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9345 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
9346 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
9347 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
9348 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
9349 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9350 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9351 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);
9354 case RENDERPATH_D3D9:
9356 // 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...
9357 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9358 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9359 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9360 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9361 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9362 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9363 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9364 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9365 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9366 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9367 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9368 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9369 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9370 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9373 case RENDERPATH_D3D10:
9374 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9376 case RENDERPATH_D3D11:
9377 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9382 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9383 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9385 case RENDERPATH_GL13:
9386 case RENDERPATH_GL11:
9387 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9389 // apply a color tint to the whole view
9390 R_ResetViewRendering2D();
9391 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9392 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9393 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9394 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9395 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9401 matrix4x4_t r_waterscrollmatrix;
9403 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9405 if (r_refdef.fog_density)
9407 r_refdef.fogcolor[0] = r_refdef.fog_red;
9408 r_refdef.fogcolor[1] = r_refdef.fog_green;
9409 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9411 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9412 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9413 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9414 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9418 VectorCopy(r_refdef.fogcolor, fogvec);
9419 // color.rgb *= ContrastBoost * SceneBrightness;
9420 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9421 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9422 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9423 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9428 void R_UpdateVariables(void)
9432 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9434 r_refdef.farclip = r_farclip_base.value;
9435 if (r_refdef.scene.worldmodel)
9436 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9437 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9439 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9440 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9441 r_refdef.polygonfactor = 0;
9442 r_refdef.polygonoffset = 0;
9443 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9444 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9446 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9447 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9448 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9449 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9450 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9451 if (FAKELIGHT_ENABLED)
9453 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9455 if (r_showsurfaces.integer)
9457 r_refdef.scene.rtworld = false;
9458 r_refdef.scene.rtworldshadows = false;
9459 r_refdef.scene.rtdlight = false;
9460 r_refdef.scene.rtdlightshadows = false;
9461 r_refdef.lightmapintensity = 0;
9464 if (gamemode == GAME_NEHAHRA)
9466 if (gl_fogenable.integer)
9468 r_refdef.oldgl_fogenable = true;
9469 r_refdef.fog_density = gl_fogdensity.value;
9470 r_refdef.fog_red = gl_fogred.value;
9471 r_refdef.fog_green = gl_foggreen.value;
9472 r_refdef.fog_blue = gl_fogblue.value;
9473 r_refdef.fog_alpha = 1;
9474 r_refdef.fog_start = 0;
9475 r_refdef.fog_end = gl_skyclip.value;
9476 r_refdef.fog_height = 1<<30;
9477 r_refdef.fog_fadedepth = 128;
9479 else if (r_refdef.oldgl_fogenable)
9481 r_refdef.oldgl_fogenable = false;
9482 r_refdef.fog_density = 0;
9483 r_refdef.fog_red = 0;
9484 r_refdef.fog_green = 0;
9485 r_refdef.fog_blue = 0;
9486 r_refdef.fog_alpha = 0;
9487 r_refdef.fog_start = 0;
9488 r_refdef.fog_end = 0;
9489 r_refdef.fog_height = 1<<30;
9490 r_refdef.fog_fadedepth = 128;
9494 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9495 r_refdef.fog_start = max(0, r_refdef.fog_start);
9496 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9498 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9500 if (r_refdef.fog_density && r_drawfog.integer)
9502 r_refdef.fogenabled = true;
9503 // this is the point where the fog reaches 0.9986 alpha, which we
9504 // consider a good enough cutoff point for the texture
9505 // (0.9986 * 256 == 255.6)
9506 if (r_fog_exp2.integer)
9507 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9509 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9510 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9511 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9512 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9513 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9514 R_BuildFogHeightTexture();
9515 // fog color was already set
9516 // update the fog texture
9517 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)
9518 R_BuildFogTexture();
9519 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9520 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9523 r_refdef.fogenabled = false;
9525 switch(vid.renderpath)
9527 case RENDERPATH_GL20:
9528 case RENDERPATH_CGGL:
9529 case RENDERPATH_D3D9:
9530 case RENDERPATH_D3D10:
9531 case RENDERPATH_D3D11:
9532 if(v_glslgamma.integer && !vid_gammatables_trivial)
9534 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9536 // build GLSL gamma texture
9537 #define RAMPWIDTH 256
9538 unsigned short ramp[RAMPWIDTH * 3];
9539 unsigned char rampbgr[RAMPWIDTH][4];
9542 r_texture_gammaramps_serial = vid_gammatables_serial;
9544 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9545 for(i = 0; i < RAMPWIDTH; ++i)
9547 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9548 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9549 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9552 if (r_texture_gammaramps)
9554 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9558 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9564 // remove GLSL gamma texture
9567 case RENDERPATH_GL13:
9568 case RENDERPATH_GL11:
9573 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9574 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9580 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9581 if( scenetype != r_currentscenetype ) {
9582 // store the old scenetype
9583 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9584 r_currentscenetype = scenetype;
9585 // move in the new scene
9586 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9595 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9597 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9598 if( scenetype == r_currentscenetype ) {
9599 return &r_refdef.scene;
9601 return &r_scenes_store[ scenetype ];
9610 void R_RenderView(void)
9612 if (r_timereport_active)
9613 R_TimeReport("start");
9614 r_textureframe++; // used only by R_GetCurrentTexture
9615 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9617 if(R_CompileShader_CheckStaticParms())
9620 if (!r_drawentities.integer)
9621 r_refdef.scene.numentities = 0;
9623 R_AnimCache_ClearCache();
9624 R_FrameData_NewFrame();
9626 if (r_refdef.view.isoverlay)
9628 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9629 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9630 R_TimeReport("depthclear");
9632 r_refdef.view.showdebug = false;
9634 r_waterstate.enabled = false;
9635 r_waterstate.numwaterplanes = 0;
9643 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9644 return; //Host_Error ("R_RenderView: NULL worldmodel");
9646 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9648 R_RenderView_UpdateViewVectors();
9650 R_Shadow_UpdateWorldLightSelection();
9652 R_Bloom_StartFrame();
9653 R_Water_StartFrame();
9656 if (r_timereport_active)
9657 R_TimeReport("viewsetup");
9659 R_ResetViewRendering3D();
9661 if (r_refdef.view.clear || r_refdef.fogenabled)
9663 R_ClearScreen(r_refdef.fogenabled);
9664 if (r_timereport_active)
9665 R_TimeReport("viewclear");
9667 r_refdef.view.clear = true;
9669 // this produces a bloom texture to be used in R_BlendView() later
9670 if (r_hdr.integer && r_bloomstate.bloomwidth)
9672 R_HDR_RenderBloomTexture();
9673 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9674 r_textureframe++; // used only by R_GetCurrentTexture
9677 r_refdef.view.showdebug = true;
9680 if (r_timereport_active)
9681 R_TimeReport("visibility");
9683 r_waterstate.numwaterplanes = 0;
9684 if (r_waterstate.enabled)
9685 R_RenderWaterPlanes();
9688 r_waterstate.numwaterplanes = 0;
9691 if (r_timereport_active)
9692 R_TimeReport("blendview");
9694 GL_Scissor(0, 0, vid.width, vid.height);
9695 GL_ScissorTest(false);
9700 void R_RenderWaterPlanes(void)
9702 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9704 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9705 if (r_timereport_active)
9706 R_TimeReport("waterworld");
9709 // don't let sound skip if going slow
9710 if (r_refdef.scene.extraupdate)
9713 R_DrawModelsAddWaterPlanes();
9714 if (r_timereport_active)
9715 R_TimeReport("watermodels");
9717 if (r_waterstate.numwaterplanes)
9719 R_Water_ProcessPlanes();
9720 if (r_timereport_active)
9721 R_TimeReport("waterscenes");
9725 extern void R_DrawLightningBeams (void);
9726 extern void VM_CL_AddPolygonsToMeshQueue (void);
9727 extern void R_DrawPortals (void);
9728 extern cvar_t cl_locs_show;
9729 static void R_DrawLocs(void);
9730 static void R_DrawEntityBBoxes(void);
9731 static void R_DrawModelDecals(void);
9732 extern void R_DrawModelShadows(void);
9733 extern void R_DrawModelShadowMaps(void);
9734 extern cvar_t cl_decals_newsystem;
9735 extern qboolean r_shadow_usingdeferredprepass;
9736 void R_RenderScene(void)
9738 qboolean shadowmapping = false;
9740 if (r_timereport_active)
9741 R_TimeReport("beginscene");
9743 r_refdef.stats.renders++;
9747 // don't let sound skip if going slow
9748 if (r_refdef.scene.extraupdate)
9751 R_MeshQueue_BeginScene();
9755 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);
9757 if (r_timereport_active)
9758 R_TimeReport("skystartframe");
9760 if (cl.csqc_vidvars.drawworld)
9762 // don't let sound skip if going slow
9763 if (r_refdef.scene.extraupdate)
9766 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9768 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9769 if (r_timereport_active)
9770 R_TimeReport("worldsky");
9773 if (R_DrawBrushModelsSky() && r_timereport_active)
9774 R_TimeReport("bmodelsky");
9776 if (skyrendermasked && skyrenderlater)
9778 // we have to force off the water clipping plane while rendering sky
9782 if (r_timereport_active)
9783 R_TimeReport("sky");
9787 R_AnimCache_CacheVisibleEntities();
9788 if (r_timereport_active)
9789 R_TimeReport("animation");
9791 R_Shadow_PrepareLights();
9792 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9793 R_Shadow_PrepareModelShadows();
9794 if (r_timereport_active)
9795 R_TimeReport("preparelights");
9797 if (R_Shadow_ShadowMappingEnabled())
9798 shadowmapping = true;
9800 if (r_shadow_usingdeferredprepass)
9801 R_Shadow_DrawPrepass();
9803 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9805 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9806 if (r_timereport_active)
9807 R_TimeReport("worlddepth");
9809 if (r_depthfirst.integer >= 2)
9811 R_DrawModelsDepth();
9812 if (r_timereport_active)
9813 R_TimeReport("modeldepth");
9816 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9818 R_DrawModelShadowMaps();
9819 R_ResetViewRendering3D();
9820 // don't let sound skip if going slow
9821 if (r_refdef.scene.extraupdate)
9825 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9827 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9828 if (r_timereport_active)
9829 R_TimeReport("world");
9832 // don't let sound skip if going slow
9833 if (r_refdef.scene.extraupdate)
9837 if (r_timereport_active)
9838 R_TimeReport("models");
9840 // don't let sound skip if going slow
9841 if (r_refdef.scene.extraupdate)
9844 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9846 R_DrawModelShadows();
9847 R_ResetViewRendering3D();
9848 // don't let sound skip if going slow
9849 if (r_refdef.scene.extraupdate)
9853 if (!r_shadow_usingdeferredprepass)
9855 R_Shadow_DrawLights();
9856 if (r_timereport_active)
9857 R_TimeReport("rtlights");
9860 // don't let sound skip if going slow
9861 if (r_refdef.scene.extraupdate)
9864 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9866 R_DrawModelShadows();
9867 R_ResetViewRendering3D();
9868 // don't let sound skip if going slow
9869 if (r_refdef.scene.extraupdate)
9873 if (cl.csqc_vidvars.drawworld)
9875 if (cl_decals_newsystem.integer)
9877 R_DrawModelDecals();
9878 if (r_timereport_active)
9879 R_TimeReport("modeldecals");
9884 if (r_timereport_active)
9885 R_TimeReport("decals");
9889 if (r_timereport_active)
9890 R_TimeReport("particles");
9893 if (r_timereport_active)
9894 R_TimeReport("explosions");
9896 R_DrawLightningBeams();
9897 if (r_timereport_active)
9898 R_TimeReport("lightning");
9901 VM_CL_AddPolygonsToMeshQueue();
9903 if (r_refdef.view.showdebug)
9905 if (cl_locs_show.integer)
9908 if (r_timereport_active)
9909 R_TimeReport("showlocs");
9912 if (r_drawportals.integer)
9915 if (r_timereport_active)
9916 R_TimeReport("portals");
9919 if (r_showbboxes.value > 0)
9921 R_DrawEntityBBoxes();
9922 if (r_timereport_active)
9923 R_TimeReport("bboxes");
9927 R_MeshQueue_RenderTransparent();
9928 if (r_timereport_active)
9929 R_TimeReport("drawtrans");
9931 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))
9933 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9934 if (r_timereport_active)
9935 R_TimeReport("worlddebug");
9936 R_DrawModelsDebug();
9937 if (r_timereport_active)
9938 R_TimeReport("modeldebug");
9941 if (cl.csqc_vidvars.drawworld)
9943 R_Shadow_DrawCoronas();
9944 if (r_timereport_active)
9945 R_TimeReport("coronas");
9950 GL_DepthTest(false);
9951 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9952 GL_Color(1, 1, 1, 1);
9953 qglBegin(GL_POLYGON);
9954 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9955 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9956 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9957 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9959 qglBegin(GL_POLYGON);
9960 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
9961 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
9962 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
9963 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
9965 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9969 // don't let sound skip if going slow
9970 if (r_refdef.scene.extraupdate)
9973 R_ResetViewRendering2D();
9976 static const unsigned short bboxelements[36] =
9986 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9989 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9991 RSurf_ActiveWorldEntity();
9993 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9994 GL_DepthMask(false);
9995 GL_DepthRange(0, 1);
9996 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9997 R_Mesh_ResetTextureState();
9999 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10000 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10001 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10002 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10003 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10004 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10005 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10006 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10007 R_FillColors(color4f, 8, cr, cg, cb, ca);
10008 if (r_refdef.fogenabled)
10010 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10012 f1 = RSurf_FogVertex(v);
10014 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10015 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10016 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10019 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10020 R_Mesh_ResetTextureState();
10021 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10022 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10025 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10029 prvm_edict_t *edict;
10030 prvm_prog_t *prog_save = prog;
10032 // this function draws bounding boxes of server entities
10036 GL_CullFace(GL_NONE);
10037 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10041 for (i = 0;i < numsurfaces;i++)
10043 edict = PRVM_EDICT_NUM(surfacelist[i]);
10044 switch ((int)edict->fields.server->solid)
10046 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10047 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10048 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10049 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10050 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10051 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10053 color[3] *= r_showbboxes.value;
10054 color[3] = bound(0, color[3], 1);
10055 GL_DepthTest(!r_showdisabledepthtest.integer);
10056 GL_CullFace(r_refdef.view.cullface_front);
10057 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10063 static void R_DrawEntityBBoxes(void)
10066 prvm_edict_t *edict;
10068 prvm_prog_t *prog_save = prog;
10070 // this function draws bounding boxes of server entities
10076 for (i = 0;i < prog->num_edicts;i++)
10078 edict = PRVM_EDICT_NUM(i);
10079 if (edict->priv.server->free)
10081 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10082 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10084 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10086 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10087 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10093 static const int nomodelelement3i[24] =
10105 static const unsigned short nomodelelement3s[24] =
10117 static const float nomodelvertex3f[6*3] =
10127 static const float nomodelcolor4f[6*4] =
10129 0.0f, 0.0f, 0.5f, 1.0f,
10130 0.0f, 0.0f, 0.5f, 1.0f,
10131 0.0f, 0.5f, 0.0f, 1.0f,
10132 0.0f, 0.5f, 0.0f, 1.0f,
10133 0.5f, 0.0f, 0.0f, 1.0f,
10134 0.5f, 0.0f, 0.0f, 1.0f
10137 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10141 float color4f[6*4];
10143 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);
10145 // this is only called once per entity so numsurfaces is always 1, and
10146 // surfacelist is always {0}, so this code does not handle batches
10148 if (rsurface.ent_flags & RENDER_ADDITIVE)
10150 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10151 GL_DepthMask(false);
10153 else if (rsurface.colormod[3] < 1)
10155 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10156 GL_DepthMask(false);
10160 GL_BlendFunc(GL_ONE, GL_ZERO);
10161 GL_DepthMask(true);
10163 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10164 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10165 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10166 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10168 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10169 for (i = 0, c = color4f;i < 6;i++, c += 4)
10171 c[0] *= rsurface.colormod[0];
10172 c[1] *= rsurface.colormod[1];
10173 c[2] *= rsurface.colormod[2];
10174 c[3] *= rsurface.colormod[3];
10176 if (r_refdef.fogenabled)
10178 for (i = 0, c = color4f;i < 6;i++, c += 4)
10180 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10182 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10183 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10184 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10187 R_Mesh_ResetTextureState();
10188 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10189 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10192 void R_DrawNoModel(entity_render_t *ent)
10195 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10196 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10197 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10199 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10202 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10204 vec3_t right1, right2, diff, normal;
10206 VectorSubtract (org2, org1, normal);
10208 // calculate 'right' vector for start
10209 VectorSubtract (r_refdef.view.origin, org1, diff);
10210 CrossProduct (normal, diff, right1);
10211 VectorNormalize (right1);
10213 // calculate 'right' vector for end
10214 VectorSubtract (r_refdef.view.origin, org2, diff);
10215 CrossProduct (normal, diff, right2);
10216 VectorNormalize (right2);
10218 vert[ 0] = org1[0] + width * right1[0];
10219 vert[ 1] = org1[1] + width * right1[1];
10220 vert[ 2] = org1[2] + width * right1[2];
10221 vert[ 3] = org1[0] - width * right1[0];
10222 vert[ 4] = org1[1] - width * right1[1];
10223 vert[ 5] = org1[2] - width * right1[2];
10224 vert[ 6] = org2[0] - width * right2[0];
10225 vert[ 7] = org2[1] - width * right2[1];
10226 vert[ 8] = org2[2] - width * right2[2];
10227 vert[ 9] = org2[0] + width * right2[0];
10228 vert[10] = org2[1] + width * right2[1];
10229 vert[11] = org2[2] + width * right2[2];
10232 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)
10234 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10235 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10236 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10237 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10238 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10239 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10240 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10241 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10242 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10243 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10244 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10245 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10248 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10253 VectorSet(v, x, y, z);
10254 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10255 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10257 if (i == mesh->numvertices)
10259 if (mesh->numvertices < mesh->maxvertices)
10261 VectorCopy(v, vertex3f);
10262 mesh->numvertices++;
10264 return mesh->numvertices;
10270 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10273 int *e, element[3];
10274 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10275 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10276 e = mesh->element3i + mesh->numtriangles * 3;
10277 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10279 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10280 if (mesh->numtriangles < mesh->maxtriangles)
10285 mesh->numtriangles++;
10287 element[1] = element[2];
10291 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10294 int *e, element[3];
10295 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10296 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10297 e = mesh->element3i + mesh->numtriangles * 3;
10298 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10300 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10301 if (mesh->numtriangles < mesh->maxtriangles)
10306 mesh->numtriangles++;
10308 element[1] = element[2];
10312 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10313 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10315 int planenum, planenum2;
10318 mplane_t *plane, *plane2;
10320 double temppoints[2][256*3];
10321 // figure out how large a bounding box we need to properly compute this brush
10323 for (w = 0;w < numplanes;w++)
10324 maxdist = max(maxdist, fabs(planes[w].dist));
10325 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10326 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10327 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10331 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10332 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10334 if (planenum2 == planenum)
10336 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);
10339 if (tempnumpoints < 3)
10341 // generate elements forming a triangle fan for this polygon
10342 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10346 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)
10348 texturelayer_t *layer;
10349 layer = t->currentlayers + t->currentnumlayers++;
10350 layer->type = type;
10351 layer->depthmask = depthmask;
10352 layer->blendfunc1 = blendfunc1;
10353 layer->blendfunc2 = blendfunc2;
10354 layer->texture = texture;
10355 layer->texmatrix = *matrix;
10356 layer->color[0] = r;
10357 layer->color[1] = g;
10358 layer->color[2] = b;
10359 layer->color[3] = a;
10362 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10364 if(parms[0] == 0 && parms[1] == 0)
10366 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10367 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10372 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10375 index = parms[2] + r_refdef.scene.time * parms[3];
10376 index -= floor(index);
10377 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10380 case Q3WAVEFUNC_NONE:
10381 case Q3WAVEFUNC_NOISE:
10382 case Q3WAVEFUNC_COUNT:
10385 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10386 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10387 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10388 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10389 case Q3WAVEFUNC_TRIANGLE:
10391 f = index - floor(index);
10394 else if (index < 2)
10396 else if (index < 3)
10402 f = parms[0] + parms[1] * f;
10403 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10404 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10408 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10413 matrix4x4_t matrix, temp;
10414 switch(tcmod->tcmod)
10416 case Q3TCMOD_COUNT:
10418 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10419 matrix = r_waterscrollmatrix;
10421 matrix = identitymatrix;
10423 case Q3TCMOD_ENTITYTRANSLATE:
10424 // this is used in Q3 to allow the gamecode to control texcoord
10425 // scrolling on the entity, which is not supported in darkplaces yet.
10426 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10428 case Q3TCMOD_ROTATE:
10429 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10430 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10431 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10433 case Q3TCMOD_SCALE:
10434 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10436 case Q3TCMOD_SCROLL:
10437 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10439 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10440 w = (int) tcmod->parms[0];
10441 h = (int) tcmod->parms[1];
10442 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10444 idx = (int) floor(f * w * h);
10445 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10447 case Q3TCMOD_STRETCH:
10448 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10449 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10451 case Q3TCMOD_TRANSFORM:
10452 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10453 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10454 VectorSet(tcmat + 6, 0 , 0 , 1);
10455 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10456 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10458 case Q3TCMOD_TURBULENT:
10459 // this is handled in the RSurf_PrepareVertices function
10460 matrix = identitymatrix;
10464 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10467 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10469 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10470 char name[MAX_QPATH];
10471 skinframe_t *skinframe;
10472 unsigned char pixels[296*194];
10473 strlcpy(cache->name, skinname, sizeof(cache->name));
10474 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10475 if (developer_loading.integer)
10476 Con_Printf("loading %s\n", name);
10477 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10478 if (!skinframe || !skinframe->base)
10481 fs_offset_t filesize;
10483 f = FS_LoadFile(name, tempmempool, true, &filesize);
10486 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10487 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10491 cache->skinframe = skinframe;
10494 texture_t *R_GetCurrentTexture(texture_t *t)
10497 const entity_render_t *ent = rsurface.entity;
10498 dp_model_t *model = ent->model;
10499 q3shaderinfo_layer_tcmod_t *tcmod;
10501 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10502 return t->currentframe;
10503 t->update_lastrenderframe = r_textureframe;
10504 t->update_lastrenderentity = (void *)ent;
10506 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10507 t->camera_entity = ent->entitynumber;
10509 t->camera_entity = 0;
10511 // switch to an alternate material if this is a q1bsp animated material
10513 texture_t *texture = t;
10514 int s = rsurface.ent_skinnum;
10515 if ((unsigned int)s >= (unsigned int)model->numskins)
10517 if (model->skinscenes)
10519 if (model->skinscenes[s].framecount > 1)
10520 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10522 s = model->skinscenes[s].firstframe;
10525 t = t + s * model->num_surfaces;
10528 // use an alternate animation if the entity's frame is not 0,
10529 // and only if the texture has an alternate animation
10530 if (rsurface.ent_alttextures && t->anim_total[1])
10531 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10533 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10535 texture->currentframe = t;
10538 // update currentskinframe to be a qw skin or animation frame
10539 if (rsurface.ent_qwskin >= 0)
10541 i = rsurface.ent_qwskin;
10542 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10544 r_qwskincache_size = cl.maxclients;
10546 Mem_Free(r_qwskincache);
10547 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10549 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10550 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10551 t->currentskinframe = r_qwskincache[i].skinframe;
10552 if (t->currentskinframe == NULL)
10553 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10555 else if (t->numskinframes >= 2)
10556 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10557 if (t->backgroundnumskinframes >= 2)
10558 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10560 t->currentmaterialflags = t->basematerialflags;
10561 t->currentalpha = rsurface.colormod[3];
10562 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10563 t->currentalpha *= r_wateralpha.value;
10564 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10565 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10566 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10567 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10568 if (!(rsurface.ent_flags & RENDER_LIGHT))
10569 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10570 else if (FAKELIGHT_ENABLED)
10572 // no modellight if using fakelight for the map
10574 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10576 // pick a model lighting mode
10577 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10578 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10580 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10582 if (rsurface.ent_flags & RENDER_ADDITIVE)
10583 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10584 else if (t->currentalpha < 1)
10585 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10586 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10587 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10588 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10589 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10590 if (t->backgroundnumskinframes)
10591 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10592 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10594 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10595 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10598 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10599 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10600 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10602 // there is no tcmod
10603 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10605 t->currenttexmatrix = r_waterscrollmatrix;
10606 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10608 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10610 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10611 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10614 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10615 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10616 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10617 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10619 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10620 if (t->currentskinframe->qpixels)
10621 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10622 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10623 if (!t->basetexture)
10624 t->basetexture = r_texture_notexture;
10625 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10626 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10627 t->nmaptexture = t->currentskinframe->nmap;
10628 if (!t->nmaptexture)
10629 t->nmaptexture = r_texture_blanknormalmap;
10630 t->glosstexture = r_texture_black;
10631 t->glowtexture = t->currentskinframe->glow;
10632 t->fogtexture = t->currentskinframe->fog;
10633 t->reflectmasktexture = t->currentskinframe->reflect;
10634 if (t->backgroundnumskinframes)
10636 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10637 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10638 t->backgroundglosstexture = r_texture_black;
10639 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10640 if (!t->backgroundnmaptexture)
10641 t->backgroundnmaptexture = r_texture_blanknormalmap;
10645 t->backgroundbasetexture = r_texture_white;
10646 t->backgroundnmaptexture = r_texture_blanknormalmap;
10647 t->backgroundglosstexture = r_texture_black;
10648 t->backgroundglowtexture = NULL;
10650 t->specularpower = r_shadow_glossexponent.value;
10651 // TODO: store reference values for these in the texture?
10652 t->specularscale = 0;
10653 if (r_shadow_gloss.integer > 0)
10655 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10657 if (r_shadow_glossintensity.value > 0)
10659 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10660 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10661 t->specularscale = r_shadow_glossintensity.value;
10664 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10666 t->glosstexture = r_texture_white;
10667 t->backgroundglosstexture = r_texture_white;
10668 t->specularscale = r_shadow_gloss2intensity.value;
10669 t->specularpower = r_shadow_gloss2exponent.value;
10672 t->specularscale *= t->specularscalemod;
10673 t->specularpower *= t->specularpowermod;
10675 // lightmaps mode looks bad with dlights using actual texturing, so turn
10676 // off the colormap and glossmap, but leave the normalmap on as it still
10677 // accurately represents the shading involved
10678 if (gl_lightmaps.integer)
10680 t->basetexture = r_texture_grey128;
10681 t->pantstexture = r_texture_black;
10682 t->shirttexture = r_texture_black;
10683 t->nmaptexture = r_texture_blanknormalmap;
10684 t->glosstexture = r_texture_black;
10685 t->glowtexture = NULL;
10686 t->fogtexture = NULL;
10687 t->reflectmasktexture = NULL;
10688 t->backgroundbasetexture = NULL;
10689 t->backgroundnmaptexture = r_texture_blanknormalmap;
10690 t->backgroundglosstexture = r_texture_black;
10691 t->backgroundglowtexture = NULL;
10692 t->specularscale = 0;
10693 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10696 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10697 VectorClear(t->dlightcolor);
10698 t->currentnumlayers = 0;
10699 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10701 int blendfunc1, blendfunc2;
10702 qboolean depthmask;
10703 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10705 blendfunc1 = GL_SRC_ALPHA;
10706 blendfunc2 = GL_ONE;
10708 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10710 blendfunc1 = GL_SRC_ALPHA;
10711 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10713 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10715 blendfunc1 = t->customblendfunc[0];
10716 blendfunc2 = t->customblendfunc[1];
10720 blendfunc1 = GL_ONE;
10721 blendfunc2 = GL_ZERO;
10723 // don't colormod evilblend textures
10724 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10725 VectorSet(t->lightmapcolor, 1, 1, 1);
10726 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10727 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10729 // fullbright is not affected by r_refdef.lightmapintensity
10730 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]);
10731 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10732 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]);
10733 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10734 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]);
10738 vec3_t ambientcolor;
10740 // set the color tint used for lights affecting this surface
10741 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10743 // q3bsp has no lightmap updates, so the lightstylevalue that
10744 // would normally be baked into the lightmap must be
10745 // applied to the color
10746 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10747 if (model->type == mod_brushq3)
10748 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10749 colorscale *= r_refdef.lightmapintensity;
10750 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10751 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10752 // basic lit geometry
10753 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]);
10754 // add pants/shirt if needed
10755 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10756 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]);
10757 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10758 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]);
10759 // now add ambient passes if needed
10760 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10762 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]);
10763 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10764 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]);
10765 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10766 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]);
10769 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10770 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]);
10771 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10773 // if this is opaque use alpha blend which will darken the earlier
10776 // if this is an alpha blended material, all the earlier passes
10777 // were darkened by fog already, so we only need to add the fog
10778 // color ontop through the fog mask texture
10780 // if this is an additive blended material, all the earlier passes
10781 // were darkened by fog already, and we should not add fog color
10782 // (because the background was not darkened, there is no fog color
10783 // that was lost behind it).
10784 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]);
10788 return t->currentframe;
10791 rsurfacestate_t rsurface;
10793 void R_Mesh_ResizeArrays(int newvertices)
10795 unsigned char *base;
10797 if (rsurface.array_size >= newvertices)
10799 if (rsurface.array_base)
10800 Mem_Free(rsurface.array_base);
10801 rsurface.array_size = (newvertices + 1023) & ~1023;
10803 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10804 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10805 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10806 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10807 size += rsurface.array_size * sizeof(float[3]);
10808 size += rsurface.array_size * sizeof(float[3]);
10809 size += rsurface.array_size * sizeof(float[3]);
10810 size += rsurface.array_size * sizeof(float[3]);
10811 size += rsurface.array_size * sizeof(float[3]);
10812 size += rsurface.array_size * sizeof(float[3]);
10813 size += rsurface.array_size * sizeof(float[3]);
10814 size += rsurface.array_size * sizeof(float[3]);
10815 size += rsurface.array_size * sizeof(float[4]);
10816 size += rsurface.array_size * sizeof(float[2]);
10817 size += rsurface.array_size * sizeof(float[2]);
10818 size += rsurface.array_size * sizeof(float[4]);
10819 size += rsurface.array_size * sizeof(int[3]);
10820 size += rsurface.array_size * sizeof(unsigned short[3]);
10821 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10822 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10823 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10824 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10825 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10826 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10827 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10828 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10829 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10830 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10831 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10832 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10833 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10834 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10835 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10836 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10837 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10838 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10839 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10842 void RSurf_ActiveWorldEntity(void)
10844 dp_model_t *model = r_refdef.scene.worldmodel;
10845 //if (rsurface.entity == r_refdef.scene.worldentity)
10847 rsurface.entity = r_refdef.scene.worldentity;
10848 rsurface.skeleton = NULL;
10849 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10850 rsurface.ent_skinnum = 0;
10851 rsurface.ent_qwskin = -1;
10852 rsurface.ent_shadertime = 0;
10853 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10854 if (rsurface.array_size < model->surfmesh.num_vertices)
10855 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10856 rsurface.matrix = identitymatrix;
10857 rsurface.inversematrix = identitymatrix;
10858 rsurface.matrixscale = 1;
10859 rsurface.inversematrixscale = 1;
10860 R_EntityMatrix(&identitymatrix);
10861 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10862 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10863 rsurface.fograngerecip = r_refdef.fograngerecip;
10864 rsurface.fogheightfade = r_refdef.fogheightfade;
10865 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10866 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10867 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10868 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10869 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10870 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10871 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10872 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10873 rsurface.colormod[3] = 1;
10874 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);
10875 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10876 rsurface.frameblend[0].lerp = 1;
10877 rsurface.ent_alttextures = false;
10878 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10879 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10880 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10881 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10882 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10883 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10884 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10885 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10886 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10887 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10888 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10889 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10890 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10891 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10892 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10893 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10894 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10895 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10896 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10897 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10898 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10899 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10900 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10901 rsurface.modelelement3i = model->surfmesh.data_element3i;
10902 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10903 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10904 rsurface.modelelement3s = model->surfmesh.data_element3s;
10905 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10906 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10907 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10908 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10909 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10910 rsurface.modelsurfaces = model->data_surfaces;
10911 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10912 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10913 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10914 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10915 rsurface.modelgeneratedvertex = false;
10916 rsurface.batchgeneratedvertex = false;
10917 rsurface.batchfirstvertex = 0;
10918 rsurface.batchnumvertices = 0;
10919 rsurface.batchfirsttriangle = 0;
10920 rsurface.batchnumtriangles = 0;
10921 rsurface.batchvertex3f = NULL;
10922 rsurface.batchvertex3f_vertexbuffer = NULL;
10923 rsurface.batchvertex3f_bufferoffset = 0;
10924 rsurface.batchsvector3f = NULL;
10925 rsurface.batchsvector3f_vertexbuffer = NULL;
10926 rsurface.batchsvector3f_bufferoffset = 0;
10927 rsurface.batchtvector3f = NULL;
10928 rsurface.batchtvector3f_vertexbuffer = NULL;
10929 rsurface.batchtvector3f_bufferoffset = 0;
10930 rsurface.batchnormal3f = NULL;
10931 rsurface.batchnormal3f_vertexbuffer = NULL;
10932 rsurface.batchnormal3f_bufferoffset = 0;
10933 rsurface.batchlightmapcolor4f = NULL;
10934 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10935 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10936 rsurface.batchtexcoordtexture2f = NULL;
10937 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10938 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10939 rsurface.batchtexcoordlightmap2f = NULL;
10940 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10941 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10942 rsurface.batchvertexmesh = NULL;
10943 rsurface.batchvertexmeshbuffer = NULL;
10944 rsurface.batchvertexposition = NULL;
10945 rsurface.batchvertexpositionbuffer = NULL;
10946 rsurface.batchelement3i = NULL;
10947 rsurface.batchelement3i_indexbuffer = NULL;
10948 rsurface.batchelement3i_bufferoffset = 0;
10949 rsurface.batchelement3s = NULL;
10950 rsurface.batchelement3s_indexbuffer = NULL;
10951 rsurface.batchelement3s_bufferoffset = 0;
10952 rsurface.passcolor4f = NULL;
10953 rsurface.passcolor4f_vertexbuffer = NULL;
10954 rsurface.passcolor4f_bufferoffset = 0;
10957 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10959 dp_model_t *model = ent->model;
10960 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10962 rsurface.entity = (entity_render_t *)ent;
10963 rsurface.skeleton = ent->skeleton;
10964 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10965 rsurface.ent_skinnum = ent->skinnum;
10966 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;
10967 rsurface.ent_shadertime = ent->shadertime;
10968 rsurface.ent_flags = ent->flags;
10969 if (rsurface.array_size < model->surfmesh.num_vertices)
10970 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10971 rsurface.matrix = ent->matrix;
10972 rsurface.inversematrix = ent->inversematrix;
10973 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10974 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10975 R_EntityMatrix(&rsurface.matrix);
10976 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10977 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10978 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10979 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10980 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10981 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10982 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10983 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10984 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10985 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10986 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10987 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10988 rsurface.colormod[3] = ent->alpha;
10989 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10990 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10991 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10992 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10993 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10994 if (ent->model->brush.submodel && !prepass)
10996 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10997 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10999 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11001 if (ent->animcache_vertex3f && !r_framedata_failed)
11003 rsurface.modelvertex3f = ent->animcache_vertex3f;
11004 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11005 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11006 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11007 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11008 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11009 rsurface.modelvertexposition = ent->animcache_vertexposition;
11010 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11012 else if (wanttangents)
11014 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11015 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11016 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11017 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11018 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11019 rsurface.modelvertexmesh = NULL;
11020 rsurface.modelvertexmeshbuffer = NULL;
11021 rsurface.modelvertexposition = NULL;
11022 rsurface.modelvertexpositionbuffer = NULL;
11024 else if (wantnormals)
11026 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11027 rsurface.modelsvector3f = NULL;
11028 rsurface.modeltvector3f = NULL;
11029 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11030 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11031 rsurface.modelvertexmesh = NULL;
11032 rsurface.modelvertexmeshbuffer = NULL;
11033 rsurface.modelvertexposition = NULL;
11034 rsurface.modelvertexpositionbuffer = NULL;
11038 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11039 rsurface.modelsvector3f = NULL;
11040 rsurface.modeltvector3f = NULL;
11041 rsurface.modelnormal3f = NULL;
11042 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11043 rsurface.modelvertexmesh = NULL;
11044 rsurface.modelvertexmeshbuffer = NULL;
11045 rsurface.modelvertexposition = NULL;
11046 rsurface.modelvertexpositionbuffer = NULL;
11048 rsurface.modelvertex3f_vertexbuffer = 0;
11049 rsurface.modelvertex3f_bufferoffset = 0;
11050 rsurface.modelsvector3f_vertexbuffer = 0;
11051 rsurface.modelsvector3f_bufferoffset = 0;
11052 rsurface.modeltvector3f_vertexbuffer = 0;
11053 rsurface.modeltvector3f_bufferoffset = 0;
11054 rsurface.modelnormal3f_vertexbuffer = 0;
11055 rsurface.modelnormal3f_bufferoffset = 0;
11056 rsurface.modelgeneratedvertex = true;
11060 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11061 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11062 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11063 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11064 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11065 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11066 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11067 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11068 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11069 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11070 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11071 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11072 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11073 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11074 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11075 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11076 rsurface.modelgeneratedvertex = false;
11078 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11079 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11080 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11081 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11082 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11083 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11084 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11085 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11086 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11087 rsurface.modelelement3i = model->surfmesh.data_element3i;
11088 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11089 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11090 rsurface.modelelement3s = model->surfmesh.data_element3s;
11091 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11092 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11093 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11094 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11095 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11096 rsurface.modelsurfaces = model->data_surfaces;
11097 rsurface.batchgeneratedvertex = false;
11098 rsurface.batchfirstvertex = 0;
11099 rsurface.batchnumvertices = 0;
11100 rsurface.batchfirsttriangle = 0;
11101 rsurface.batchnumtriangles = 0;
11102 rsurface.batchvertex3f = NULL;
11103 rsurface.batchvertex3f_vertexbuffer = NULL;
11104 rsurface.batchvertex3f_bufferoffset = 0;
11105 rsurface.batchsvector3f = NULL;
11106 rsurface.batchsvector3f_vertexbuffer = NULL;
11107 rsurface.batchsvector3f_bufferoffset = 0;
11108 rsurface.batchtvector3f = NULL;
11109 rsurface.batchtvector3f_vertexbuffer = NULL;
11110 rsurface.batchtvector3f_bufferoffset = 0;
11111 rsurface.batchnormal3f = NULL;
11112 rsurface.batchnormal3f_vertexbuffer = NULL;
11113 rsurface.batchnormal3f_bufferoffset = 0;
11114 rsurface.batchlightmapcolor4f = NULL;
11115 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11116 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11117 rsurface.batchtexcoordtexture2f = NULL;
11118 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11119 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11120 rsurface.batchtexcoordlightmap2f = NULL;
11121 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11122 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11123 rsurface.batchvertexmesh = NULL;
11124 rsurface.batchvertexmeshbuffer = NULL;
11125 rsurface.batchvertexposition = NULL;
11126 rsurface.batchvertexpositionbuffer = NULL;
11127 rsurface.batchelement3i = NULL;
11128 rsurface.batchelement3i_indexbuffer = NULL;
11129 rsurface.batchelement3i_bufferoffset = 0;
11130 rsurface.batchelement3s = NULL;
11131 rsurface.batchelement3s_indexbuffer = NULL;
11132 rsurface.batchelement3s_bufferoffset = 0;
11133 rsurface.passcolor4f = NULL;
11134 rsurface.passcolor4f_vertexbuffer = NULL;
11135 rsurface.passcolor4f_bufferoffset = 0;
11138 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)
11142 rsurface.entity = r_refdef.scene.worldentity;
11143 rsurface.skeleton = NULL;
11144 rsurface.ent_skinnum = 0;
11145 rsurface.ent_qwskin = -1;
11146 rsurface.ent_shadertime = shadertime;
11147 rsurface.ent_flags = entflags;
11148 rsurface.modelnumvertices = numvertices;
11149 rsurface.modelnumtriangles = numtriangles;
11150 if (rsurface.array_size < rsurface.modelnumvertices)
11151 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11152 rsurface.matrix = *matrix;
11153 rsurface.inversematrix = *inversematrix;
11154 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11155 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11156 R_EntityMatrix(&rsurface.matrix);
11157 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11158 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11159 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11160 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11161 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11162 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11163 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11164 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11165 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11166 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11167 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11168 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11169 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);
11170 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11171 rsurface.frameblend[0].lerp = 1;
11172 rsurface.ent_alttextures = false;
11173 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11174 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11177 rsurface.modelvertex3f = vertex3f;
11178 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11179 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11180 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11182 else if (wantnormals)
11184 rsurface.modelvertex3f = vertex3f;
11185 rsurface.modelsvector3f = NULL;
11186 rsurface.modeltvector3f = NULL;
11187 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11191 rsurface.modelvertex3f = vertex3f;
11192 rsurface.modelsvector3f = NULL;
11193 rsurface.modeltvector3f = NULL;
11194 rsurface.modelnormal3f = NULL;
11196 rsurface.modelvertexmesh = NULL;
11197 rsurface.modelvertexmeshbuffer = NULL;
11198 rsurface.modelvertexposition = NULL;
11199 rsurface.modelvertexpositionbuffer = NULL;
11200 rsurface.modelvertex3f_vertexbuffer = 0;
11201 rsurface.modelvertex3f_bufferoffset = 0;
11202 rsurface.modelsvector3f_vertexbuffer = 0;
11203 rsurface.modelsvector3f_bufferoffset = 0;
11204 rsurface.modeltvector3f_vertexbuffer = 0;
11205 rsurface.modeltvector3f_bufferoffset = 0;
11206 rsurface.modelnormal3f_vertexbuffer = 0;
11207 rsurface.modelnormal3f_bufferoffset = 0;
11208 rsurface.modelgeneratedvertex = true;
11209 rsurface.modellightmapcolor4f = color4f;
11210 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11211 rsurface.modellightmapcolor4f_bufferoffset = 0;
11212 rsurface.modeltexcoordtexture2f = texcoord2f;
11213 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11214 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11215 rsurface.modeltexcoordlightmap2f = NULL;
11216 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11217 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11218 rsurface.modelelement3i = element3i;
11219 rsurface.modelelement3i_indexbuffer = NULL;
11220 rsurface.modelelement3i_bufferoffset = 0;
11221 rsurface.modelelement3s = element3s;
11222 rsurface.modelelement3s_indexbuffer = NULL;
11223 rsurface.modelelement3s_bufferoffset = 0;
11224 rsurface.modellightmapoffsets = NULL;
11225 rsurface.modelsurfaces = NULL;
11226 rsurface.batchgeneratedvertex = false;
11227 rsurface.batchfirstvertex = 0;
11228 rsurface.batchnumvertices = 0;
11229 rsurface.batchfirsttriangle = 0;
11230 rsurface.batchnumtriangles = 0;
11231 rsurface.batchvertex3f = NULL;
11232 rsurface.batchvertex3f_vertexbuffer = NULL;
11233 rsurface.batchvertex3f_bufferoffset = 0;
11234 rsurface.batchsvector3f = NULL;
11235 rsurface.batchsvector3f_vertexbuffer = NULL;
11236 rsurface.batchsvector3f_bufferoffset = 0;
11237 rsurface.batchtvector3f = NULL;
11238 rsurface.batchtvector3f_vertexbuffer = NULL;
11239 rsurface.batchtvector3f_bufferoffset = 0;
11240 rsurface.batchnormal3f = NULL;
11241 rsurface.batchnormal3f_vertexbuffer = NULL;
11242 rsurface.batchnormal3f_bufferoffset = 0;
11243 rsurface.batchlightmapcolor4f = NULL;
11244 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11245 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11246 rsurface.batchtexcoordtexture2f = NULL;
11247 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11248 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11249 rsurface.batchtexcoordlightmap2f = NULL;
11250 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11251 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11252 rsurface.batchvertexmesh = NULL;
11253 rsurface.batchvertexmeshbuffer = NULL;
11254 rsurface.batchvertexposition = NULL;
11255 rsurface.batchvertexpositionbuffer = NULL;
11256 rsurface.batchelement3i = NULL;
11257 rsurface.batchelement3i_indexbuffer = NULL;
11258 rsurface.batchelement3i_bufferoffset = 0;
11259 rsurface.batchelement3s = NULL;
11260 rsurface.batchelement3s_indexbuffer = NULL;
11261 rsurface.batchelement3s_bufferoffset = 0;
11262 rsurface.passcolor4f = NULL;
11263 rsurface.passcolor4f_vertexbuffer = NULL;
11264 rsurface.passcolor4f_bufferoffset = 0;
11266 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11268 if ((wantnormals || wanttangents) && !normal3f)
11270 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11271 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11273 if (wanttangents && !svector3f)
11275 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);
11276 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11277 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11281 // now convert arrays into vertexmesh structs
11282 for (i = 0;i < numvertices;i++)
11284 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11285 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11286 if (rsurface.modelsvector3f)
11287 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11288 if (rsurface.modeltvector3f)
11289 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11290 if (rsurface.modelnormal3f)
11291 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11292 if (rsurface.modellightmapcolor4f)
11293 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11294 if (rsurface.modeltexcoordtexture2f)
11295 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11296 if (rsurface.modeltexcoordlightmap2f)
11297 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11301 float RSurf_FogPoint(const float *v)
11303 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11304 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11305 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11306 float FogHeightFade = r_refdef.fogheightfade;
11308 unsigned int fogmasktableindex;
11309 if (r_refdef.fogplaneviewabove)
11310 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11312 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11313 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11314 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11317 float RSurf_FogVertex(const float *v)
11319 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11320 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11321 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11322 float FogHeightFade = rsurface.fogheightfade;
11324 unsigned int fogmasktableindex;
11325 if (r_refdef.fogplaneviewabove)
11326 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11328 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11329 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11330 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11333 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11336 for (i = 0;i < numelements;i++)
11337 outelement3i[i] = inelement3i[i] + adjust;
11340 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11341 extern cvar_t gl_vbo;
11342 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11350 int surfacefirsttriangle;
11351 int surfacenumtriangles;
11352 int surfacefirstvertex;
11353 int surfaceendvertex;
11354 int surfacenumvertices;
11358 qboolean dynamicvertex;
11362 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11363 float waveparms[4];
11364 q3shaderinfo_deform_t *deform;
11365 const msurface_t *surface, *firstsurface;
11366 r_vertexposition_t *vertexposition;
11367 r_vertexmesh_t *vertexmesh;
11368 if (!texturenumsurfaces)
11370 // find vertex range of this surface batch
11372 firstsurface = texturesurfacelist[0];
11373 firsttriangle = firstsurface->num_firsttriangle;
11375 firstvertex = endvertex = firstsurface->num_firstvertex;
11376 for (i = 0;i < texturenumsurfaces;i++)
11378 surface = texturesurfacelist[i];
11379 if (surface != firstsurface + i)
11381 surfacefirstvertex = surface->num_firstvertex;
11382 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11383 surfacenumtriangles = surface->num_triangles;
11384 if (firstvertex > surfacefirstvertex)
11385 firstvertex = surfacefirstvertex;
11386 if (endvertex < surfaceendvertex)
11387 endvertex = surfaceendvertex;
11388 numtriangles += surfacenumtriangles;
11393 // we now know the vertex range used, and if there are any gaps in it
11394 rsurface.batchfirstvertex = firstvertex;
11395 rsurface.batchnumvertices = endvertex - firstvertex;
11396 rsurface.batchfirsttriangle = firsttriangle;
11397 rsurface.batchnumtriangles = numtriangles;
11399 // this variable holds flags for which properties have been updated that
11400 // may require regenerating vertexmesh or vertexposition arrays...
11403 // check if any dynamic vertex processing must occur
11404 dynamicvertex = false;
11406 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11407 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11408 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11410 switch (deform->deform)
11413 case Q3DEFORM_PROJECTIONSHADOW:
11414 case Q3DEFORM_TEXT0:
11415 case Q3DEFORM_TEXT1:
11416 case Q3DEFORM_TEXT2:
11417 case Q3DEFORM_TEXT3:
11418 case Q3DEFORM_TEXT4:
11419 case Q3DEFORM_TEXT5:
11420 case Q3DEFORM_TEXT6:
11421 case Q3DEFORM_TEXT7:
11422 case Q3DEFORM_NONE:
11424 case Q3DEFORM_AUTOSPRITE:
11425 dynamicvertex = true;
11426 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11427 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11429 case Q3DEFORM_AUTOSPRITE2:
11430 dynamicvertex = true;
11431 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11432 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11434 case Q3DEFORM_NORMAL:
11435 dynamicvertex = true;
11436 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11437 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11439 case Q3DEFORM_WAVE:
11440 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11441 break; // if wavefunc is a nop, ignore this transform
11442 dynamicvertex = true;
11443 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11444 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11446 case Q3DEFORM_BULGE:
11447 dynamicvertex = true;
11448 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11449 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11451 case Q3DEFORM_MOVE:
11452 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11453 break; // if wavefunc is a nop, ignore this transform
11454 dynamicvertex = true;
11455 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11456 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11460 switch(rsurface.texture->tcgen.tcgen)
11463 case Q3TCGEN_TEXTURE:
11465 case Q3TCGEN_LIGHTMAP:
11466 dynamicvertex = true;
11467 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11468 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11470 case Q3TCGEN_VECTOR:
11471 dynamicvertex = true;
11472 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11473 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11475 case Q3TCGEN_ENVIRONMENT:
11476 dynamicvertex = true;
11477 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11478 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11481 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11483 dynamicvertex = true;
11484 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11485 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11488 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11490 dynamicvertex = true;
11491 batchneed |= BATCHNEED_NOGAPS;
11492 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11495 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11497 dynamicvertex = true;
11498 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11499 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11502 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11504 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11505 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11506 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11507 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11508 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11509 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11510 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11513 // when the model data has no vertex buffer (dynamic mesh), we need to
11515 if (!rsurface.modelvertexmeshbuffer)
11516 batchneed |= BATCHNEED_NOGAPS;
11518 // if needsupdate, we have to do a dynamic vertex batch for sure
11519 if (needsupdate & batchneed)
11520 dynamicvertex = true;
11522 // see if we need to build vertexmesh from arrays
11523 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11524 dynamicvertex = true;
11526 // see if we need to build vertexposition from arrays
11527 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11528 dynamicvertex = true;
11530 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11531 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11532 dynamicvertex = true;
11534 // if there is a chance of animated vertex colors, it's a dynamic batch
11535 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11536 dynamicvertex = true;
11538 rsurface.batchvertex3f = rsurface.modelvertex3f;
11539 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11540 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11541 rsurface.batchsvector3f = rsurface.modelsvector3f;
11542 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11543 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11544 rsurface.batchtvector3f = rsurface.modeltvector3f;
11545 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11546 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11547 rsurface.batchnormal3f = rsurface.modelnormal3f;
11548 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11549 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11550 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11551 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11552 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11553 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11554 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11555 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11556 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11557 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11558 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11559 rsurface.batchvertexposition = rsurface.modelvertexposition;
11560 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11561 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11562 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11563 rsurface.batchelement3i = rsurface.modelelement3i;
11564 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11565 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11566 rsurface.batchelement3s = rsurface.modelelement3s;
11567 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11568 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11570 // if any dynamic vertex processing has to occur in software, we copy the
11571 // entire surface list together before processing to rebase the vertices
11572 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11574 // if any gaps exist and we do not have a static vertex buffer, we have to
11575 // copy the surface list together to avoid wasting upload bandwidth on the
11576 // vertices in the gaps.
11578 // if gaps exist and we have a static vertex buffer, we still have to
11579 // combine the index buffer ranges into one dynamic index buffer.
11581 // in all cases we end up with data that can be drawn in one call.
11583 if (!dynamicvertex)
11585 // static vertex data, just set pointers...
11586 rsurface.batchgeneratedvertex = false;
11587 // if there are gaps, we want to build a combined index buffer,
11588 // otherwise use the original static buffer with an appropriate offset
11593 for (i = 0;i < texturenumsurfaces;i++)
11595 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11596 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11597 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11598 numtriangles += surfacenumtriangles;
11600 rsurface.batchelement3i = rsurface.array_batchelement3i;
11601 rsurface.batchelement3i_indexbuffer = NULL;
11602 rsurface.batchelement3i_bufferoffset = 0;
11603 rsurface.batchelement3s = NULL;
11604 rsurface.batchelement3s_indexbuffer = NULL;
11605 rsurface.batchelement3s_bufferoffset = 0;
11606 if (endvertex <= 65536)
11608 rsurface.batchelement3s = rsurface.array_batchelement3s;
11609 for (i = 0;i < numtriangles*3;i++)
11610 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11612 rsurface.batchfirsttriangle = firsttriangle;
11613 rsurface.batchnumtriangles = numtriangles;
11618 // something needs software processing, do it for real...
11619 // we only directly handle interleaved array data in this case...
11620 rsurface.batchgeneratedvertex = true;
11622 // now copy the vertex data into a combined array and make an index array
11623 // (this is what Quake3 does all the time)
11624 //if (gaps || rsurface.batchfirstvertex)
11626 rsurface.batchvertexposition = NULL;
11627 rsurface.batchvertexpositionbuffer = NULL;
11628 rsurface.batchvertexmesh = NULL;
11629 rsurface.batchvertexmeshbuffer = NULL;
11630 rsurface.batchvertex3f = NULL;
11631 rsurface.batchvertex3f_vertexbuffer = NULL;
11632 rsurface.batchvertex3f_bufferoffset = 0;
11633 rsurface.batchsvector3f = NULL;
11634 rsurface.batchsvector3f_vertexbuffer = NULL;
11635 rsurface.batchsvector3f_bufferoffset = 0;
11636 rsurface.batchtvector3f = NULL;
11637 rsurface.batchtvector3f_vertexbuffer = NULL;
11638 rsurface.batchtvector3f_bufferoffset = 0;
11639 rsurface.batchnormal3f = NULL;
11640 rsurface.batchnormal3f_vertexbuffer = NULL;
11641 rsurface.batchnormal3f_bufferoffset = 0;
11642 rsurface.batchlightmapcolor4f = NULL;
11643 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11644 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11645 rsurface.batchtexcoordtexture2f = NULL;
11646 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11647 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11648 rsurface.batchtexcoordlightmap2f = NULL;
11649 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11650 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11651 rsurface.batchelement3i = rsurface.array_batchelement3i;
11652 rsurface.batchelement3i_indexbuffer = NULL;
11653 rsurface.batchelement3i_bufferoffset = 0;
11654 rsurface.batchelement3s = NULL;
11655 rsurface.batchelement3s_indexbuffer = NULL;
11656 rsurface.batchelement3s_bufferoffset = 0;
11657 // we'll only be setting up certain arrays as needed
11658 if (batchneed & BATCHNEED_VERTEXPOSITION)
11659 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11660 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11661 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11662 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11663 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11664 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11665 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11666 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11668 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11669 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11671 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11672 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11673 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11674 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11675 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11676 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11679 for (i = 0;i < texturenumsurfaces;i++)
11681 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11682 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11683 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11684 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11685 // copy only the data requested
11686 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11687 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11688 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11689 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11690 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11692 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11693 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11694 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11695 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11696 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11698 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11699 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11701 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11702 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11703 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11704 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11705 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11706 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11708 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11709 numvertices += surfacenumvertices;
11710 numtriangles += surfacenumtriangles;
11713 // generate a 16bit index array as well if possible
11714 // (in general, dynamic batches fit)
11715 if (numvertices <= 65536)
11717 rsurface.batchelement3s = rsurface.array_batchelement3s;
11718 for (i = 0;i < numtriangles*3;i++)
11719 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11722 // since we've copied everything, the batch now starts at 0
11723 rsurface.batchfirstvertex = 0;
11724 rsurface.batchnumvertices = numvertices;
11725 rsurface.batchfirsttriangle = 0;
11726 rsurface.batchnumtriangles = numtriangles;
11729 // q1bsp surfaces rendered in vertex color mode have to have colors
11730 // calculated based on lightstyles
11731 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11733 // generate color arrays for the surfaces in this list
11737 const int *offsets;
11738 const unsigned char *lm;
11740 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11741 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11742 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11743 for (i = 0;i < texturenumsurfaces;i++)
11745 surface = texturesurfacelist[i];
11746 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11747 surfacenumvertices = surface->num_vertices;
11748 if (surface->lightmapinfo->samples)
11750 for (j = 0;j < surfacenumvertices;j++)
11752 lm = surface->lightmapinfo->samples + offsets[j];
11753 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11754 VectorScale(lm, scale, c);
11755 if (surface->lightmapinfo->styles[1] != 255)
11757 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11759 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11760 VectorMA(c, scale, lm, c);
11761 if (surface->lightmapinfo->styles[2] != 255)
11764 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11765 VectorMA(c, scale, lm, c);
11766 if (surface->lightmapinfo->styles[3] != 255)
11769 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11770 VectorMA(c, scale, lm, c);
11777 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);
11783 for (j = 0;j < surfacenumvertices;j++)
11785 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11792 // if vertices are deformed (sprite flares and things in maps, possibly
11793 // water waves, bulges and other deformations), modify the copied vertices
11795 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11797 switch (deform->deform)
11800 case Q3DEFORM_PROJECTIONSHADOW:
11801 case Q3DEFORM_TEXT0:
11802 case Q3DEFORM_TEXT1:
11803 case Q3DEFORM_TEXT2:
11804 case Q3DEFORM_TEXT3:
11805 case Q3DEFORM_TEXT4:
11806 case Q3DEFORM_TEXT5:
11807 case Q3DEFORM_TEXT6:
11808 case Q3DEFORM_TEXT7:
11809 case Q3DEFORM_NONE:
11811 case Q3DEFORM_AUTOSPRITE:
11812 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11813 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11814 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11815 VectorNormalize(newforward);
11816 VectorNormalize(newright);
11817 VectorNormalize(newup);
11818 // a single autosprite surface can contain multiple sprites...
11819 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11821 VectorClear(center);
11822 for (i = 0;i < 4;i++)
11823 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11824 VectorScale(center, 0.25f, center);
11825 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11826 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11827 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11828 for (i = 0;i < 4;i++)
11830 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11831 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11834 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11835 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11836 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);
11837 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11838 rsurface.batchvertex3f_vertexbuffer = NULL;
11839 rsurface.batchvertex3f_bufferoffset = 0;
11840 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11841 rsurface.batchsvector3f_vertexbuffer = NULL;
11842 rsurface.batchsvector3f_bufferoffset = 0;
11843 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11844 rsurface.batchtvector3f_vertexbuffer = NULL;
11845 rsurface.batchtvector3f_bufferoffset = 0;
11846 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11847 rsurface.batchnormal3f_vertexbuffer = NULL;
11848 rsurface.batchnormal3f_bufferoffset = 0;
11850 case Q3DEFORM_AUTOSPRITE2:
11851 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11852 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11853 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11854 VectorNormalize(newforward);
11855 VectorNormalize(newright);
11856 VectorNormalize(newup);
11858 const float *v1, *v2;
11868 memset(shortest, 0, sizeof(shortest));
11869 // a single autosprite surface can contain multiple sprites...
11870 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11872 VectorClear(center);
11873 for (i = 0;i < 4;i++)
11874 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11875 VectorScale(center, 0.25f, center);
11876 // find the two shortest edges, then use them to define the
11877 // axis vectors for rotating around the central axis
11878 for (i = 0;i < 6;i++)
11880 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11881 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11882 l = VectorDistance2(v1, v2);
11883 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11884 if (v1[2] != v2[2])
11885 l += (1.0f / 1024.0f);
11886 if (shortest[0].length2 > l || i == 0)
11888 shortest[1] = shortest[0];
11889 shortest[0].length2 = l;
11890 shortest[0].v1 = v1;
11891 shortest[0].v2 = v2;
11893 else if (shortest[1].length2 > l || i == 1)
11895 shortest[1].length2 = l;
11896 shortest[1].v1 = v1;
11897 shortest[1].v2 = v2;
11900 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11901 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11902 // this calculates the right vector from the shortest edge
11903 // and the up vector from the edge midpoints
11904 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11905 VectorNormalize(right);
11906 VectorSubtract(end, start, up);
11907 VectorNormalize(up);
11908 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11909 VectorSubtract(rsurface.localvieworigin, center, forward);
11910 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11911 VectorNegate(forward, forward);
11912 VectorReflect(forward, 0, up, forward);
11913 VectorNormalize(forward);
11914 CrossProduct(up, forward, newright);
11915 VectorNormalize(newright);
11916 // rotate the quad around the up axis vector, this is made
11917 // especially easy by the fact we know the quad is flat,
11918 // so we only have to subtract the center position and
11919 // measure distance along the right vector, and then
11920 // multiply that by the newright vector and add back the
11922 // we also need to subtract the old position to undo the
11923 // displacement from the center, which we do with a
11924 // DotProduct, the subtraction/addition of center is also
11925 // optimized into DotProducts here
11926 l = DotProduct(right, center);
11927 for (i = 0;i < 4;i++)
11929 v1 = rsurface.batchvertex3f + 3*(j+i);
11930 f = DotProduct(right, v1) - l;
11931 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11935 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11936 rsurface.batchvertex3f_vertexbuffer = NULL;
11937 rsurface.batchvertex3f_bufferoffset = 0;
11938 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11940 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11941 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11942 rsurface.batchnormal3f_vertexbuffer = NULL;
11943 rsurface.batchnormal3f_bufferoffset = 0;
11945 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11947 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);
11948 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11949 rsurface.batchsvector3f_vertexbuffer = NULL;
11950 rsurface.batchsvector3f_bufferoffset = 0;
11951 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11952 rsurface.batchtvector3f_vertexbuffer = NULL;
11953 rsurface.batchtvector3f_bufferoffset = 0;
11956 case Q3DEFORM_NORMAL:
11957 // deform the normals to make reflections wavey
11958 for (j = 0;j < rsurface.batchnumvertices;j++)
11961 float *normal = rsurface.array_batchnormal3f + 3*j;
11962 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11963 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11964 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]);
11965 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]);
11966 VectorNormalize(normal);
11968 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11969 rsurface.batchnormal3f_vertexbuffer = NULL;
11970 rsurface.batchnormal3f_bufferoffset = 0;
11971 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11973 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);
11974 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11975 rsurface.batchsvector3f_vertexbuffer = NULL;
11976 rsurface.batchsvector3f_bufferoffset = 0;
11977 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11978 rsurface.batchtvector3f_vertexbuffer = NULL;
11979 rsurface.batchtvector3f_bufferoffset = 0;
11982 case Q3DEFORM_WAVE:
11983 // deform vertex array to make wavey water and flags and such
11984 waveparms[0] = deform->waveparms[0];
11985 waveparms[1] = deform->waveparms[1];
11986 waveparms[2] = deform->waveparms[2];
11987 waveparms[3] = deform->waveparms[3];
11988 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11989 break; // if wavefunc is a nop, don't make a dynamic vertex array
11990 // this is how a divisor of vertex influence on deformation
11991 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11992 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11993 for (j = 0;j < rsurface.batchnumvertices;j++)
11995 // if the wavefunc depends on time, evaluate it per-vertex
11998 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11999 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12001 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12003 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12004 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12005 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12006 rsurface.batchvertex3f_vertexbuffer = NULL;
12007 rsurface.batchvertex3f_bufferoffset = 0;
12008 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12009 rsurface.batchnormal3f_vertexbuffer = NULL;
12010 rsurface.batchnormal3f_bufferoffset = 0;
12011 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12013 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);
12014 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12015 rsurface.batchsvector3f_vertexbuffer = NULL;
12016 rsurface.batchsvector3f_bufferoffset = 0;
12017 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12018 rsurface.batchtvector3f_vertexbuffer = NULL;
12019 rsurface.batchtvector3f_bufferoffset = 0;
12022 case Q3DEFORM_BULGE:
12023 // deform vertex array to make the surface have moving bulges
12024 for (j = 0;j < rsurface.batchnumvertices;j++)
12026 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12027 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12029 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12030 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12031 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12032 rsurface.batchvertex3f_vertexbuffer = NULL;
12033 rsurface.batchvertex3f_bufferoffset = 0;
12034 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12035 rsurface.batchnormal3f_vertexbuffer = NULL;
12036 rsurface.batchnormal3f_bufferoffset = 0;
12037 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12039 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);
12040 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12041 rsurface.batchsvector3f_vertexbuffer = NULL;
12042 rsurface.batchsvector3f_bufferoffset = 0;
12043 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12044 rsurface.batchtvector3f_vertexbuffer = NULL;
12045 rsurface.batchtvector3f_bufferoffset = 0;
12048 case Q3DEFORM_MOVE:
12049 // deform vertex array
12050 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12051 break; // if wavefunc is a nop, don't make a dynamic vertex array
12052 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12053 VectorScale(deform->parms, scale, waveparms);
12054 for (j = 0;j < rsurface.batchnumvertices;j++)
12055 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12056 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12057 rsurface.batchvertex3f_vertexbuffer = NULL;
12058 rsurface.batchvertex3f_bufferoffset = 0;
12063 // generate texcoords based on the chosen texcoord source
12064 switch(rsurface.texture->tcgen.tcgen)
12067 case Q3TCGEN_TEXTURE:
12069 case Q3TCGEN_LIGHTMAP:
12070 if (rsurface.batchtexcoordlightmap2f)
12071 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12072 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12073 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12074 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12076 case Q3TCGEN_VECTOR:
12077 for (j = 0;j < rsurface.batchnumvertices;j++)
12079 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12080 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12082 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12083 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12084 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12086 case Q3TCGEN_ENVIRONMENT:
12087 // make environment reflections using a spheremap
12088 for (j = 0;j < rsurface.batchnumvertices;j++)
12090 // identical to Q3A's method, but executed in worldspace so
12091 // carried models can be shiny too
12093 float viewer[3], d, reflected[3], worldreflected[3];
12095 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12096 // VectorNormalize(viewer);
12098 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12100 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12101 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12102 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12103 // note: this is proportinal to viewer, so we can normalize later
12105 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12106 VectorNormalize(worldreflected);
12108 // note: this sphere map only uses world x and z!
12109 // so positive and negative y will LOOK THE SAME.
12110 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12111 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12113 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12114 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12115 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12118 // the only tcmod that needs software vertex processing is turbulent, so
12119 // check for it here and apply the changes if needed
12120 // and we only support that as the first one
12121 // (handling a mixture of turbulent and other tcmods would be problematic
12122 // without punting it entirely to a software path)
12123 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12125 amplitude = rsurface.texture->tcmods[0].parms[1];
12126 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12127 for (j = 0;j < rsurface.batchnumvertices;j++)
12129 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);
12130 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12132 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12133 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12134 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12137 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12139 // convert the modified arrays to vertex structs
12140 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12141 rsurface.batchvertexmeshbuffer = NULL;
12142 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12143 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12144 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12145 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12146 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12147 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12148 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12150 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12152 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12153 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12156 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12157 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12158 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12159 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12160 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12161 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12162 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12163 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12164 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12167 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12169 // convert the modified arrays to vertex structs
12170 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12171 rsurface.batchvertexpositionbuffer = NULL;
12172 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12173 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12175 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12176 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12180 void RSurf_DrawBatch(void)
12182 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);
12185 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12187 // pick the closest matching water plane
12188 int planeindex, vertexindex, bestplaneindex = -1;
12192 r_waterstate_waterplane_t *p;
12194 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12196 if(p->camera_entity != rsurface.texture->camera_entity)
12199 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12200 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12202 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12203 d += fabs(PlaneDiff(vert, &p->plane));
12205 if (bestd > d || bestplaneindex < 0)
12208 bestplaneindex = planeindex;
12211 return bestplaneindex;
12214 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12217 for (i = 0;i < rsurface.batchnumvertices;i++)
12218 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12219 rsurface.passcolor4f = rsurface.array_passcolor4f;
12220 rsurface.passcolor4f_vertexbuffer = 0;
12221 rsurface.passcolor4f_bufferoffset = 0;
12224 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12231 if (rsurface.passcolor4f)
12233 // generate color arrays
12234 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)
12236 f = RSurf_FogVertex(v);
12245 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12247 f = RSurf_FogVertex(v);
12254 rsurface.passcolor4f = rsurface.array_passcolor4f;
12255 rsurface.passcolor4f_vertexbuffer = 0;
12256 rsurface.passcolor4f_bufferoffset = 0;
12259 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12266 if (!rsurface.passcolor4f)
12268 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)
12270 f = RSurf_FogVertex(v);
12271 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12272 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12273 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12276 rsurface.passcolor4f = rsurface.array_passcolor4f;
12277 rsurface.passcolor4f_vertexbuffer = 0;
12278 rsurface.passcolor4f_bufferoffset = 0;
12281 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12286 if (!rsurface.passcolor4f)
12288 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12295 rsurface.passcolor4f = rsurface.array_passcolor4f;
12296 rsurface.passcolor4f_vertexbuffer = 0;
12297 rsurface.passcolor4f_bufferoffset = 0;
12300 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12305 if (!rsurface.passcolor4f)
12307 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12309 c2[0] = c[0] + r_refdef.scene.ambient;
12310 c2[1] = c[1] + r_refdef.scene.ambient;
12311 c2[2] = c[2] + r_refdef.scene.ambient;
12314 rsurface.passcolor4f = rsurface.array_passcolor4f;
12315 rsurface.passcolor4f_vertexbuffer = 0;
12316 rsurface.passcolor4f_bufferoffset = 0;
12319 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12322 rsurface.passcolor4f = NULL;
12323 rsurface.passcolor4f_vertexbuffer = 0;
12324 rsurface.passcolor4f_bufferoffset = 0;
12325 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12326 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12327 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12328 GL_Color(r, g, b, a);
12329 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12333 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12335 // TODO: optimize applyfog && applycolor case
12336 // just apply fog if necessary, and tint the fog color array if necessary
12337 rsurface.passcolor4f = NULL;
12338 rsurface.passcolor4f_vertexbuffer = 0;
12339 rsurface.passcolor4f_bufferoffset = 0;
12340 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12341 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12342 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12343 GL_Color(r, g, b, a);
12347 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12350 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12351 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12352 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12353 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12354 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12355 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12356 GL_Color(r, g, b, a);
12360 static void RSurf_DrawBatch_GL11_ClampColor(void)
12365 if (!rsurface.passcolor4f)
12367 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12369 c2[0] = bound(0.0f, c1[0], 1.0f);
12370 c2[1] = bound(0.0f, c1[1], 1.0f);
12371 c2[2] = bound(0.0f, c1[2], 1.0f);
12372 c2[3] = bound(0.0f, c1[3], 1.0f);
12376 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12386 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)
12388 f = -DotProduct(r_refdef.view.forward, n);
12390 f = f * 0.85 + 0.15; // work around so stuff won't get black
12391 f *= r_refdef.lightmapintensity;
12392 Vector4Set(c, f, f, f, 1);
12395 rsurface.passcolor4f = rsurface.array_passcolor4f;
12396 rsurface.passcolor4f_vertexbuffer = 0;
12397 rsurface.passcolor4f_bufferoffset = 0;
12400 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12402 RSurf_DrawBatch_GL11_ApplyFakeLight();
12403 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12404 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12405 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12406 GL_Color(r, g, b, a);
12410 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12418 vec3_t ambientcolor;
12419 vec3_t diffusecolor;
12423 VectorCopy(rsurface.modellight_lightdir, lightdir);
12424 f = 0.5f * r_refdef.lightmapintensity;
12425 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12426 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12427 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12428 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12429 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12430 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12432 if (VectorLength2(diffusecolor) > 0)
12434 // q3-style directional shading
12435 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)
12437 if ((f = DotProduct(n, lightdir)) > 0)
12438 VectorMA(ambientcolor, f, diffusecolor, c);
12440 VectorCopy(ambientcolor, c);
12447 rsurface.passcolor4f = rsurface.array_passcolor4f;
12448 rsurface.passcolor4f_vertexbuffer = 0;
12449 rsurface.passcolor4f_bufferoffset = 0;
12450 *applycolor = false;
12454 *r = ambientcolor[0];
12455 *g = ambientcolor[1];
12456 *b = ambientcolor[2];
12457 rsurface.passcolor4f = NULL;
12458 rsurface.passcolor4f_vertexbuffer = 0;
12459 rsurface.passcolor4f_bufferoffset = 0;
12463 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12465 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12466 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12467 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12468 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12469 GL_Color(r, g, b, a);
12473 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12479 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12481 f = 1 - RSurf_FogVertex(v);
12489 void RSurf_SetupDepthAndCulling(void)
12491 // submodels are biased to avoid z-fighting with world surfaces that they
12492 // may be exactly overlapping (avoids z-fighting artifacts on certain
12493 // doors and things in Quake maps)
12494 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12495 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12496 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12497 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12500 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12502 // transparent sky would be ridiculous
12503 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12505 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12506 skyrenderlater = true;
12507 RSurf_SetupDepthAndCulling();
12508 GL_DepthMask(true);
12509 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12510 // skymasking on them, and Quake3 never did sky masking (unlike
12511 // software Quake and software Quake2), so disable the sky masking
12512 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12513 // and skymasking also looks very bad when noclipping outside the
12514 // level, so don't use it then either.
12515 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12517 R_Mesh_ResetTextureState();
12518 if (skyrendermasked)
12520 R_SetupShader_DepthOrShadow();
12521 // depth-only (masking)
12522 GL_ColorMask(0,0,0,0);
12523 // just to make sure that braindead drivers don't draw
12524 // anything despite that colormask...
12525 GL_BlendFunc(GL_ZERO, GL_ONE);
12526 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12527 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12531 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12533 GL_BlendFunc(GL_ONE, GL_ZERO);
12534 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12535 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12536 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12539 if (skyrendermasked)
12540 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12542 R_Mesh_ResetTextureState();
12543 GL_Color(1, 1, 1, 1);
12546 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12547 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12548 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12550 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12554 // render screenspace normalmap to texture
12555 GL_DepthMask(true);
12556 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12561 // bind lightmap texture
12563 // water/refraction/reflection/camera surfaces have to be handled specially
12564 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12566 int start, end, startplaneindex;
12567 for (start = 0;start < texturenumsurfaces;start = end)
12569 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12570 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12572 // now that we have a batch using the same planeindex, render it
12573 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12575 // render water or distortion background
12576 GL_DepthMask(true);
12577 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));
12579 // blend surface on top
12580 GL_DepthMask(false);
12581 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12584 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12586 // render surface with reflection texture as input
12587 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12588 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));
12595 // render surface batch normally
12596 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12597 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12601 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12603 // OpenGL 1.3 path - anything not completely ancient
12604 qboolean applycolor;
12607 const texturelayer_t *layer;
12608 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);
12609 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12611 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12614 int layertexrgbscale;
12615 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12617 if (layerindex == 0)
12618 GL_AlphaTest(true);
12621 GL_AlphaTest(false);
12622 GL_DepthFunc(GL_EQUAL);
12625 GL_DepthMask(layer->depthmask && writedepth);
12626 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12627 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12629 layertexrgbscale = 4;
12630 VectorScale(layer->color, 0.25f, layercolor);
12632 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12634 layertexrgbscale = 2;
12635 VectorScale(layer->color, 0.5f, layercolor);
12639 layertexrgbscale = 1;
12640 VectorScale(layer->color, 1.0f, layercolor);
12642 layercolor[3] = layer->color[3];
12643 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12644 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12645 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12646 switch (layer->type)
12648 case TEXTURELAYERTYPE_LITTEXTURE:
12649 // single-pass lightmapped texture with 2x rgbscale
12650 R_Mesh_TexBind(0, r_texture_white);
12651 R_Mesh_TexMatrix(0, NULL);
12652 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12653 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12654 R_Mesh_TexBind(1, layer->texture);
12655 R_Mesh_TexMatrix(1, &layer->texmatrix);
12656 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12657 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12658 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12659 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12660 else if (FAKELIGHT_ENABLED)
12661 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12662 else if (rsurface.uselightmaptexture)
12663 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12665 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12667 case TEXTURELAYERTYPE_TEXTURE:
12668 // singletexture unlit texture with transparency support
12669 R_Mesh_TexBind(0, layer->texture);
12670 R_Mesh_TexMatrix(0, &layer->texmatrix);
12671 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12672 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12673 R_Mesh_TexBind(1, 0);
12674 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12675 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12677 case TEXTURELAYERTYPE_FOG:
12678 // singletexture fogging
12679 if (layer->texture)
12681 R_Mesh_TexBind(0, layer->texture);
12682 R_Mesh_TexMatrix(0, &layer->texmatrix);
12683 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12684 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12688 R_Mesh_TexBind(0, 0);
12689 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12691 R_Mesh_TexBind(1, 0);
12692 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12693 // generate a color array for the fog pass
12694 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12695 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12699 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12702 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12704 GL_DepthFunc(GL_LEQUAL);
12705 GL_AlphaTest(false);
12709 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12711 // OpenGL 1.1 - crusty old voodoo path
12714 const texturelayer_t *layer;
12715 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);
12716 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12718 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12720 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12722 if (layerindex == 0)
12723 GL_AlphaTest(true);
12726 GL_AlphaTest(false);
12727 GL_DepthFunc(GL_EQUAL);
12730 GL_DepthMask(layer->depthmask && writedepth);
12731 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12732 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12733 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12734 switch (layer->type)
12736 case TEXTURELAYERTYPE_LITTEXTURE:
12737 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12739 // two-pass lit texture with 2x rgbscale
12740 // first the lightmap pass
12741 R_Mesh_TexBind(0, r_texture_white);
12742 R_Mesh_TexMatrix(0, NULL);
12743 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12744 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12745 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12746 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12747 else if (FAKELIGHT_ENABLED)
12748 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12749 else if (rsurface.uselightmaptexture)
12750 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12752 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12753 // then apply the texture to it
12754 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12755 R_Mesh_TexBind(0, layer->texture);
12756 R_Mesh_TexMatrix(0, &layer->texmatrix);
12757 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12758 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12759 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);
12763 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12764 R_Mesh_TexBind(0, layer->texture);
12765 R_Mesh_TexMatrix(0, &layer->texmatrix);
12766 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12767 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12768 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12769 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);
12771 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);
12774 case TEXTURELAYERTYPE_TEXTURE:
12775 // singletexture unlit texture with transparency support
12776 R_Mesh_TexBind(0, layer->texture);
12777 R_Mesh_TexMatrix(0, &layer->texmatrix);
12778 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12779 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12780 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);
12782 case TEXTURELAYERTYPE_FOG:
12783 // singletexture fogging
12784 if (layer->texture)
12786 R_Mesh_TexBind(0, layer->texture);
12787 R_Mesh_TexMatrix(0, &layer->texmatrix);
12788 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12789 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12793 R_Mesh_TexBind(0, 0);
12794 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12796 // generate a color array for the fog pass
12797 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12798 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12802 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12805 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12807 GL_DepthFunc(GL_LEQUAL);
12808 GL_AlphaTest(false);
12812 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12816 r_vertexgeneric_t *batchvertex;
12819 GL_AlphaTest(false);
12820 R_Mesh_ResetTextureState();
12821 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12823 if(rsurface.texture && rsurface.texture->currentskinframe)
12825 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12826 c[3] *= rsurface.texture->currentalpha;
12836 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12838 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12839 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12840 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12843 // brighten it up (as texture value 127 means "unlit")
12844 c[0] *= 2 * r_refdef.view.colorscale;
12845 c[1] *= 2 * r_refdef.view.colorscale;
12846 c[2] *= 2 * r_refdef.view.colorscale;
12848 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12849 c[3] *= r_wateralpha.value;
12851 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12853 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12854 GL_DepthMask(false);
12856 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12858 GL_BlendFunc(GL_ONE, GL_ONE);
12859 GL_DepthMask(false);
12861 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12863 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12864 GL_DepthMask(false);
12866 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12868 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12869 GL_DepthMask(false);
12873 GL_BlendFunc(GL_ONE, GL_ZERO);
12874 GL_DepthMask(writedepth);
12877 if (r_showsurfaces.integer == 3)
12879 rsurface.passcolor4f = NULL;
12881 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12883 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12885 rsurface.passcolor4f = NULL;
12886 rsurface.passcolor4f_vertexbuffer = 0;
12887 rsurface.passcolor4f_bufferoffset = 0;
12889 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12891 qboolean applycolor = true;
12894 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12896 r_refdef.lightmapintensity = 1;
12897 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12898 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12900 else if (FAKELIGHT_ENABLED)
12902 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12904 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12905 RSurf_DrawBatch_GL11_ApplyFakeLight();
12906 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12910 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12912 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12913 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12914 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12917 if(!rsurface.passcolor4f)
12918 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12920 RSurf_DrawBatch_GL11_ApplyAmbient();
12921 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12922 if(r_refdef.fogenabled)
12923 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12924 RSurf_DrawBatch_GL11_ClampColor();
12926 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12927 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12930 else if (!r_refdef.view.showdebug)
12932 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12933 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12934 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12936 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12937 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12939 R_Mesh_PrepareVertices_Generic_Unlock();
12942 else if (r_showsurfaces.integer == 4)
12944 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12945 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12946 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12948 unsigned char c = vi << 3;
12949 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12950 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12952 R_Mesh_PrepareVertices_Generic_Unlock();
12955 else if (r_showsurfaces.integer == 2)
12958 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12959 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12960 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12962 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12963 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12964 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12965 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12966 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12967 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12968 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12970 R_Mesh_PrepareVertices_Generic_Unlock();
12971 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12975 int texturesurfaceindex;
12977 const msurface_t *surface;
12978 unsigned char surfacecolor4ub[4];
12979 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12980 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12982 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12984 surface = texturesurfacelist[texturesurfaceindex];
12985 k = (int)(((size_t)surface) / sizeof(msurface_t));
12986 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12987 for (j = 0;j < surface->num_vertices;j++)
12989 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12990 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12994 R_Mesh_PrepareVertices_Generic_Unlock();
12999 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13002 RSurf_SetupDepthAndCulling();
13003 if (r_showsurfaces.integer)
13005 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13008 switch (vid.renderpath)
13010 case RENDERPATH_GL20:
13011 case RENDERPATH_CGGL:
13012 case RENDERPATH_D3D9:
13013 case RENDERPATH_D3D10:
13014 case RENDERPATH_D3D11:
13015 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13017 case RENDERPATH_GL13:
13018 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13020 case RENDERPATH_GL11:
13021 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13027 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13030 RSurf_SetupDepthAndCulling();
13031 if (r_showsurfaces.integer)
13033 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13036 switch (vid.renderpath)
13038 case RENDERPATH_GL20:
13039 case RENDERPATH_CGGL:
13040 case RENDERPATH_D3D9:
13041 case RENDERPATH_D3D10:
13042 case RENDERPATH_D3D11:
13043 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13045 case RENDERPATH_GL13:
13046 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13048 case RENDERPATH_GL11:
13049 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13055 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13058 int texturenumsurfaces, endsurface;
13059 texture_t *texture;
13060 const msurface_t *surface;
13061 #define MAXBATCH_TRANSPARENTSURFACES 256
13062 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13064 // if the model is static it doesn't matter what value we give for
13065 // wantnormals and wanttangents, so this logic uses only rules applicable
13066 // to a model, knowing that they are meaningless otherwise
13067 if (ent == r_refdef.scene.worldentity)
13068 RSurf_ActiveWorldEntity();
13069 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13070 RSurf_ActiveModelEntity(ent, false, false, false);
13073 switch (vid.renderpath)
13075 case RENDERPATH_GL20:
13076 case RENDERPATH_CGGL:
13077 case RENDERPATH_D3D9:
13078 case RENDERPATH_D3D10:
13079 case RENDERPATH_D3D11:
13080 RSurf_ActiveModelEntity(ent, true, true, false);
13082 case RENDERPATH_GL13:
13083 case RENDERPATH_GL11:
13084 RSurf_ActiveModelEntity(ent, true, false, false);
13089 if (r_transparentdepthmasking.integer)
13091 qboolean setup = false;
13092 for (i = 0;i < numsurfaces;i = j)
13095 surface = rsurface.modelsurfaces + surfacelist[i];
13096 texture = surface->texture;
13097 rsurface.texture = R_GetCurrentTexture(texture);
13098 rsurface.lightmaptexture = NULL;
13099 rsurface.deluxemaptexture = NULL;
13100 rsurface.uselightmaptexture = false;
13101 // scan ahead until we find a different texture
13102 endsurface = min(i + 1024, numsurfaces);
13103 texturenumsurfaces = 0;
13104 texturesurfacelist[texturenumsurfaces++] = surface;
13105 for (;j < endsurface;j++)
13107 surface = rsurface.modelsurfaces + surfacelist[j];
13108 if (texture != surface->texture)
13110 texturesurfacelist[texturenumsurfaces++] = surface;
13112 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13114 // render the range of surfaces as depth
13118 GL_ColorMask(0,0,0,0);
13120 GL_DepthTest(true);
13121 GL_BlendFunc(GL_ONE, GL_ZERO);
13122 GL_DepthMask(true);
13123 GL_AlphaTest(false);
13124 R_Mesh_ResetTextureState();
13125 R_SetupShader_DepthOrShadow();
13127 RSurf_SetupDepthAndCulling();
13128 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13129 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13133 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13136 for (i = 0;i < numsurfaces;i = j)
13139 surface = rsurface.modelsurfaces + surfacelist[i];
13140 texture = surface->texture;
13141 rsurface.texture = R_GetCurrentTexture(texture);
13142 // scan ahead until we find a different texture
13143 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13144 texturenumsurfaces = 0;
13145 texturesurfacelist[texturenumsurfaces++] = surface;
13146 if(FAKELIGHT_ENABLED)
13148 rsurface.lightmaptexture = NULL;
13149 rsurface.deluxemaptexture = NULL;
13150 rsurface.uselightmaptexture = false;
13151 for (;j < endsurface;j++)
13153 surface = rsurface.modelsurfaces + surfacelist[j];
13154 if (texture != surface->texture)
13156 texturesurfacelist[texturenumsurfaces++] = surface;
13161 rsurface.lightmaptexture = surface->lightmaptexture;
13162 rsurface.deluxemaptexture = surface->deluxemaptexture;
13163 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13164 for (;j < endsurface;j++)
13166 surface = rsurface.modelsurfaces + surfacelist[j];
13167 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13169 texturesurfacelist[texturenumsurfaces++] = surface;
13172 // render the range of surfaces
13173 if (ent == r_refdef.scene.worldentity)
13174 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13176 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13178 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13179 GL_AlphaTest(false);
13182 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13184 // transparent surfaces get pushed off into the transparent queue
13185 int surfacelistindex;
13186 const msurface_t *surface;
13187 vec3_t tempcenter, center;
13188 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13190 surface = texturesurfacelist[surfacelistindex];
13191 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13192 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13193 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13194 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13195 if (queueentity->transparent_offset) // transparent offset
13197 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13198 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13199 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13201 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13205 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13207 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13209 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13211 RSurf_SetupDepthAndCulling();
13212 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13213 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13217 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13219 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13222 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13225 if (!rsurface.texture->currentnumlayers)
13227 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13228 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13230 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13232 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13233 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13234 else if (!rsurface.texture->currentnumlayers)
13236 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13238 // in the deferred case, transparent surfaces were queued during prepass
13239 if (!r_shadow_usingdeferredprepass)
13240 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13244 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13245 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13250 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13253 texture_t *texture;
13254 // break the surface list down into batches by texture and use of lightmapping
13255 for (i = 0;i < numsurfaces;i = j)
13258 // texture is the base texture pointer, rsurface.texture is the
13259 // current frame/skin the texture is directing us to use (for example
13260 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13261 // use skin 1 instead)
13262 texture = surfacelist[i]->texture;
13263 rsurface.texture = R_GetCurrentTexture(texture);
13264 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13266 // if this texture is not the kind we want, skip ahead to the next one
13267 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13271 if(FAKELIGHT_ENABLED || depthonly || prepass)
13273 rsurface.lightmaptexture = NULL;
13274 rsurface.deluxemaptexture = NULL;
13275 rsurface.uselightmaptexture = false;
13276 // simply scan ahead until we find a different texture or lightmap state
13277 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13282 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13283 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13284 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13285 // simply scan ahead until we find a different texture or lightmap state
13286 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13289 // render the range of surfaces
13290 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13294 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13298 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13301 if (!rsurface.texture->currentnumlayers)
13303 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13304 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13306 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13308 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13309 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13310 else if (!rsurface.texture->currentnumlayers)
13312 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13314 // in the deferred case, transparent surfaces were queued during prepass
13315 if (!r_shadow_usingdeferredprepass)
13316 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13320 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13321 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13326 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13329 texture_t *texture;
13330 // break the surface list down into batches by texture and use of lightmapping
13331 for (i = 0;i < numsurfaces;i = j)
13334 // texture is the base texture pointer, rsurface.texture is the
13335 // current frame/skin the texture is directing us to use (for example
13336 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13337 // use skin 1 instead)
13338 texture = surfacelist[i]->texture;
13339 rsurface.texture = R_GetCurrentTexture(texture);
13340 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13342 // if this texture is not the kind we want, skip ahead to the next one
13343 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13347 if(FAKELIGHT_ENABLED || depthonly || prepass)
13349 rsurface.lightmaptexture = NULL;
13350 rsurface.deluxemaptexture = NULL;
13351 rsurface.uselightmaptexture = false;
13352 // simply scan ahead until we find a different texture or lightmap state
13353 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13358 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13359 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13360 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13361 // simply scan ahead until we find a different texture or lightmap state
13362 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13365 // render the range of surfaces
13366 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13370 float locboxvertex3f[6*4*3] =
13372 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13373 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13374 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13375 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13376 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13377 1,0,0, 0,0,0, 0,1,0, 1,1,0
13380 unsigned short locboxelements[6*2*3] =
13385 12,13,14, 12,14,15,
13386 16,17,18, 16,18,19,
13390 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13393 cl_locnode_t *loc = (cl_locnode_t *)ent;
13395 float vertex3f[6*4*3];
13397 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13398 GL_DepthMask(false);
13399 GL_DepthRange(0, 1);
13400 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13401 GL_DepthTest(true);
13402 GL_CullFace(GL_NONE);
13403 R_EntityMatrix(&identitymatrix);
13405 R_Mesh_ResetTextureState();
13407 i = surfacelist[0];
13408 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13409 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13410 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13411 surfacelist[0] < 0 ? 0.5f : 0.125f);
13413 if (VectorCompare(loc->mins, loc->maxs))
13415 VectorSet(size, 2, 2, 2);
13416 VectorMA(loc->mins, -0.5f, size, mins);
13420 VectorCopy(loc->mins, mins);
13421 VectorSubtract(loc->maxs, loc->mins, size);
13424 for (i = 0;i < 6*4*3;)
13425 for (j = 0;j < 3;j++, i++)
13426 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13428 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13429 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13430 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13433 void R_DrawLocs(void)
13436 cl_locnode_t *loc, *nearestloc;
13438 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13439 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13441 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13442 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13446 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13448 if (decalsystem->decals)
13449 Mem_Free(decalsystem->decals);
13450 memset(decalsystem, 0, sizeof(*decalsystem));
13453 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)
13456 tridecal_t *decals;
13459 // expand or initialize the system
13460 if (decalsystem->maxdecals <= decalsystem->numdecals)
13462 decalsystem_t old = *decalsystem;
13463 qboolean useshortelements;
13464 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13465 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13466 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)));
13467 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13468 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13469 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13470 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13471 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13472 if (decalsystem->numdecals)
13473 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13475 Mem_Free(old.decals);
13476 for (i = 0;i < decalsystem->maxdecals*3;i++)
13477 decalsystem->element3i[i] = i;
13478 if (useshortelements)
13479 for (i = 0;i < decalsystem->maxdecals*3;i++)
13480 decalsystem->element3s[i] = i;
13483 // grab a decal and search for another free slot for the next one
13484 decals = decalsystem->decals;
13485 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13486 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13488 decalsystem->freedecal = i;
13489 if (decalsystem->numdecals <= i)
13490 decalsystem->numdecals = i + 1;
13492 // initialize the decal
13494 decal->triangleindex = triangleindex;
13495 decal->surfaceindex = surfaceindex;
13496 decal->decalsequence = decalsequence;
13497 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13498 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13499 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13500 decal->color4ub[0][3] = 255;
13501 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13502 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13503 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13504 decal->color4ub[1][3] = 255;
13505 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13506 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13507 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13508 decal->color4ub[2][3] = 255;
13509 decal->vertex3f[0][0] = v0[0];
13510 decal->vertex3f[0][1] = v0[1];
13511 decal->vertex3f[0][2] = v0[2];
13512 decal->vertex3f[1][0] = v1[0];
13513 decal->vertex3f[1][1] = v1[1];
13514 decal->vertex3f[1][2] = v1[2];
13515 decal->vertex3f[2][0] = v2[0];
13516 decal->vertex3f[2][1] = v2[1];
13517 decal->vertex3f[2][2] = v2[2];
13518 decal->texcoord2f[0][0] = t0[0];
13519 decal->texcoord2f[0][1] = t0[1];
13520 decal->texcoord2f[1][0] = t1[0];
13521 decal->texcoord2f[1][1] = t1[1];
13522 decal->texcoord2f[2][0] = t2[0];
13523 decal->texcoord2f[2][1] = t2[1];
13526 extern cvar_t cl_decals_bias;
13527 extern cvar_t cl_decals_models;
13528 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13529 // baseparms, parms, temps
13530 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)
13535 const float *vertex3f;
13537 float points[2][9][3];
13544 e = rsurface.modelelement3i + 3*triangleindex;
13546 vertex3f = rsurface.modelvertex3f;
13548 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13550 index = 3*e[cornerindex];
13551 VectorCopy(vertex3f + index, v[cornerindex]);
13554 //TriangleNormal(v[0], v[1], v[2], normal);
13555 //if (DotProduct(normal, localnormal) < 0.0f)
13557 // clip by each of the box planes formed from the projection matrix
13558 // if anything survives, we emit the decal
13559 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]);
13562 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]);
13565 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]);
13568 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]);
13571 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]);
13574 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]);
13577 // some part of the triangle survived, so we have to accept it...
13580 // dynamic always uses the original triangle
13582 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13584 index = 3*e[cornerindex];
13585 VectorCopy(vertex3f + index, v[cornerindex]);
13588 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13590 // convert vertex positions to texcoords
13591 Matrix4x4_Transform(projection, v[cornerindex], temp);
13592 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13593 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13594 // calculate distance fade from the projection origin
13595 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13596 f = bound(0.0f, f, 1.0f);
13597 c[cornerindex][0] = r * f;
13598 c[cornerindex][1] = g * f;
13599 c[cornerindex][2] = b * f;
13600 c[cornerindex][3] = 1.0f;
13601 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13604 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);
13606 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13607 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);
13609 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)
13611 matrix4x4_t projection;
13612 decalsystem_t *decalsystem;
13615 const msurface_t *surface;
13616 const msurface_t *surfaces;
13617 const int *surfacelist;
13618 const texture_t *texture;
13620 int numsurfacelist;
13621 int surfacelistindex;
13624 float localorigin[3];
13625 float localnormal[3];
13626 float localmins[3];
13627 float localmaxs[3];
13630 float planes[6][4];
13633 int bih_triangles_count;
13634 int bih_triangles[256];
13635 int bih_surfaces[256];
13637 decalsystem = &ent->decalsystem;
13638 model = ent->model;
13639 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13641 R_DecalSystem_Reset(&ent->decalsystem);
13645 if (!model->brush.data_leafs && !cl_decals_models.integer)
13647 if (decalsystem->model)
13648 R_DecalSystem_Reset(decalsystem);
13652 if (decalsystem->model != model)
13653 R_DecalSystem_Reset(decalsystem);
13654 decalsystem->model = model;
13656 RSurf_ActiveModelEntity(ent, false, false, false);
13658 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13659 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13660 VectorNormalize(localnormal);
13661 localsize = worldsize*rsurface.inversematrixscale;
13662 localmins[0] = localorigin[0] - localsize;
13663 localmins[1] = localorigin[1] - localsize;
13664 localmins[2] = localorigin[2] - localsize;
13665 localmaxs[0] = localorigin[0] + localsize;
13666 localmaxs[1] = localorigin[1] + localsize;
13667 localmaxs[2] = localorigin[2] + localsize;
13669 //VectorCopy(localnormal, planes[4]);
13670 //VectorVectors(planes[4], planes[2], planes[0]);
13671 AnglesFromVectors(angles, localnormal, NULL, false);
13672 AngleVectors(angles, planes[0], planes[2], planes[4]);
13673 VectorNegate(planes[0], planes[1]);
13674 VectorNegate(planes[2], planes[3]);
13675 VectorNegate(planes[4], planes[5]);
13676 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13677 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13678 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13679 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13680 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13681 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13686 matrix4x4_t forwardprojection;
13687 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13688 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13693 float projectionvector[4][3];
13694 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13695 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13696 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13697 projectionvector[0][0] = planes[0][0] * ilocalsize;
13698 projectionvector[0][1] = planes[1][0] * ilocalsize;
13699 projectionvector[0][2] = planes[2][0] * ilocalsize;
13700 projectionvector[1][0] = planes[0][1] * ilocalsize;
13701 projectionvector[1][1] = planes[1][1] * ilocalsize;
13702 projectionvector[1][2] = planes[2][1] * ilocalsize;
13703 projectionvector[2][0] = planes[0][2] * ilocalsize;
13704 projectionvector[2][1] = planes[1][2] * ilocalsize;
13705 projectionvector[2][2] = planes[2][2] * ilocalsize;
13706 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13707 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13708 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13709 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13713 dynamic = model->surfmesh.isanimated;
13714 numsurfacelist = model->nummodelsurfaces;
13715 surfacelist = model->sortedmodelsurfaces;
13716 surfaces = model->data_surfaces;
13719 bih_triangles_count = -1;
13722 if(model->render_bih.numleafs)
13723 bih = &model->render_bih;
13724 else if(model->collision_bih.numleafs)
13725 bih = &model->collision_bih;
13728 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13729 if(bih_triangles_count == 0)
13731 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13733 if(bih_triangles_count > 0)
13735 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13737 surfaceindex = bih_surfaces[triangleindex];
13738 surface = surfaces + surfaceindex;
13739 texture = surface->texture;
13740 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13742 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13744 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13749 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13751 surfaceindex = surfacelist[surfacelistindex];
13752 surface = surfaces + surfaceindex;
13753 // check cull box first because it rejects more than any other check
13754 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13756 // skip transparent surfaces
13757 texture = surface->texture;
13758 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13760 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13762 numtriangles = surface->num_triangles;
13763 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13764 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13769 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13770 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)
13772 int renderentityindex;
13773 float worldmins[3];
13774 float worldmaxs[3];
13775 entity_render_t *ent;
13777 if (!cl_decals_newsystem.integer)
13780 worldmins[0] = worldorigin[0] - worldsize;
13781 worldmins[1] = worldorigin[1] - worldsize;
13782 worldmins[2] = worldorigin[2] - worldsize;
13783 worldmaxs[0] = worldorigin[0] + worldsize;
13784 worldmaxs[1] = worldorigin[1] + worldsize;
13785 worldmaxs[2] = worldorigin[2] + worldsize;
13787 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13789 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13791 ent = r_refdef.scene.entities[renderentityindex];
13792 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13795 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13799 typedef struct r_decalsystem_splatqueue_s
13801 vec3_t worldorigin;
13802 vec3_t worldnormal;
13808 r_decalsystem_splatqueue_t;
13810 int r_decalsystem_numqueued = 0;
13811 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13813 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)
13815 r_decalsystem_splatqueue_t *queue;
13817 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13820 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13821 VectorCopy(worldorigin, queue->worldorigin);
13822 VectorCopy(worldnormal, queue->worldnormal);
13823 Vector4Set(queue->color, r, g, b, a);
13824 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13825 queue->worldsize = worldsize;
13826 queue->decalsequence = cl.decalsequence++;
13829 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13832 r_decalsystem_splatqueue_t *queue;
13834 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13835 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);
13836 r_decalsystem_numqueued = 0;
13839 extern cvar_t cl_decals_max;
13840 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13843 decalsystem_t *decalsystem = &ent->decalsystem;
13850 if (!decalsystem->numdecals)
13853 if (r_showsurfaces.integer)
13856 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13858 R_DecalSystem_Reset(decalsystem);
13862 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13863 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13865 if (decalsystem->lastupdatetime)
13866 frametime = (cl.time - decalsystem->lastupdatetime);
13869 decalsystem->lastupdatetime = cl.time;
13870 decal = decalsystem->decals;
13871 numdecals = decalsystem->numdecals;
13873 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13875 if (decal->color4ub[0][3])
13877 decal->lived += frametime;
13878 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13880 memset(decal, 0, sizeof(*decal));
13881 if (decalsystem->freedecal > i)
13882 decalsystem->freedecal = i;
13886 decal = decalsystem->decals;
13887 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13890 // collapse the array by shuffling the tail decals into the gaps
13893 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13894 decalsystem->freedecal++;
13895 if (decalsystem->freedecal == numdecals)
13897 decal[decalsystem->freedecal] = decal[--numdecals];
13900 decalsystem->numdecals = numdecals;
13902 if (numdecals <= 0)
13904 // if there are no decals left, reset decalsystem
13905 R_DecalSystem_Reset(decalsystem);
13909 extern skinframe_t *decalskinframe;
13910 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13913 decalsystem_t *decalsystem = &ent->decalsystem;
13922 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13925 numdecals = decalsystem->numdecals;
13929 if (r_showsurfaces.integer)
13932 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13934 R_DecalSystem_Reset(decalsystem);
13938 // if the model is static it doesn't matter what value we give for
13939 // wantnormals and wanttangents, so this logic uses only rules applicable
13940 // to a model, knowing that they are meaningless otherwise
13941 if (ent == r_refdef.scene.worldentity)
13942 RSurf_ActiveWorldEntity();
13944 RSurf_ActiveModelEntity(ent, false, false, false);
13946 decalsystem->lastupdatetime = cl.time;
13947 decal = decalsystem->decals;
13949 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13951 // update vertex positions for animated models
13952 v3f = decalsystem->vertex3f;
13953 c4f = decalsystem->color4f;
13954 t2f = decalsystem->texcoord2f;
13955 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13957 if (!decal->color4ub[0][3])
13960 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13963 // update color values for fading decals
13964 if (decal->lived >= cl_decals_time.value)
13966 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13967 alpha *= (1.0f/255.0f);
13970 alpha = 1.0f/255.0f;
13972 c4f[ 0] = decal->color4ub[0][0] * alpha;
13973 c4f[ 1] = decal->color4ub[0][1] * alpha;
13974 c4f[ 2] = decal->color4ub[0][2] * alpha;
13976 c4f[ 4] = decal->color4ub[1][0] * alpha;
13977 c4f[ 5] = decal->color4ub[1][1] * alpha;
13978 c4f[ 6] = decal->color4ub[1][2] * alpha;
13980 c4f[ 8] = decal->color4ub[2][0] * alpha;
13981 c4f[ 9] = decal->color4ub[2][1] * alpha;
13982 c4f[10] = decal->color4ub[2][2] * alpha;
13985 t2f[0] = decal->texcoord2f[0][0];
13986 t2f[1] = decal->texcoord2f[0][1];
13987 t2f[2] = decal->texcoord2f[1][0];
13988 t2f[3] = decal->texcoord2f[1][1];
13989 t2f[4] = decal->texcoord2f[2][0];
13990 t2f[5] = decal->texcoord2f[2][1];
13992 // update vertex positions for animated models
13993 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13995 e = rsurface.modelelement3i + 3*decal->triangleindex;
13996 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13997 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13998 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
14002 VectorCopy(decal->vertex3f[0], v3f);
14003 VectorCopy(decal->vertex3f[1], v3f + 3);
14004 VectorCopy(decal->vertex3f[2], v3f + 6);
14007 if (r_refdef.fogenabled)
14009 alpha = RSurf_FogVertex(v3f);
14010 VectorScale(c4f, alpha, c4f);
14011 alpha = RSurf_FogVertex(v3f + 3);
14012 VectorScale(c4f + 4, alpha, c4f + 4);
14013 alpha = RSurf_FogVertex(v3f + 6);
14014 VectorScale(c4f + 8, alpha, c4f + 8);
14025 r_refdef.stats.drawndecals += numtris;
14027 // now render the decals all at once
14028 // (this assumes they all use one particle font texture!)
14029 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);
14030 R_Mesh_ResetTextureState();
14031 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14032 GL_DepthMask(false);
14033 GL_DepthRange(0, 1);
14034 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14035 GL_DepthTest(true);
14036 GL_CullFace(GL_NONE);
14037 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14038 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14039 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14043 static void R_DrawModelDecals(void)
14047 // fade faster when there are too many decals
14048 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14049 for (i = 0;i < r_refdef.scene.numentities;i++)
14050 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14052 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14053 for (i = 0;i < r_refdef.scene.numentities;i++)
14054 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14055 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14057 R_DecalSystem_ApplySplatEntitiesQueue();
14059 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14060 for (i = 0;i < r_refdef.scene.numentities;i++)
14061 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14063 r_refdef.stats.totaldecals += numdecals;
14065 if (r_showsurfaces.integer)
14068 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14070 for (i = 0;i < r_refdef.scene.numentities;i++)
14072 if (!r_refdef.viewcache.entityvisible[i])
14074 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14075 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14079 extern cvar_t mod_collision_bih;
14080 void R_DrawDebugModel(void)
14082 entity_render_t *ent = rsurface.entity;
14083 int i, j, k, l, flagsmask;
14084 const msurface_t *surface;
14085 dp_model_t *model = ent->model;
14088 switch(vid.renderpath)
14090 case RENDERPATH_GL11:
14091 case RENDERPATH_GL13:
14092 case RENDERPATH_GL20:
14093 case RENDERPATH_CGGL:
14095 case RENDERPATH_D3D9:
14096 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14098 case RENDERPATH_D3D10:
14099 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14101 case RENDERPATH_D3D11:
14102 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14106 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14108 R_Mesh_ResetTextureState();
14109 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14110 GL_DepthRange(0, 1);
14111 GL_DepthTest(!r_showdisabledepthtest.integer);
14112 GL_DepthMask(false);
14113 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14115 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14119 qboolean cullbox = ent == r_refdef.scene.worldentity;
14120 const q3mbrush_t *brush;
14121 const bih_t *bih = &model->collision_bih;
14122 const bih_leaf_t *bihleaf;
14123 float vertex3f[3][3];
14124 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14126 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14128 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14130 switch (bihleaf->type)
14133 brush = model->brush.data_brushes + bihleaf->itemindex;
14134 if (brush->colbrushf && brush->colbrushf->numtriangles)
14136 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);
14137 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14138 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14141 case BIH_COLLISIONTRIANGLE:
14142 triangleindex = bihleaf->itemindex;
14143 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14144 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14145 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14146 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);
14147 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14148 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14150 case BIH_RENDERTRIANGLE:
14151 triangleindex = bihleaf->itemindex;
14152 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14153 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14154 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14155 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);
14156 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14157 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14163 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14165 if (r_showtris.integer || r_shownormals.integer)
14167 if (r_showdisabledepthtest.integer)
14169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14170 GL_DepthMask(false);
14174 GL_BlendFunc(GL_ONE, GL_ZERO);
14175 GL_DepthMask(true);
14177 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14179 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14181 rsurface.texture = R_GetCurrentTexture(surface->texture);
14182 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14184 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14185 if (r_showtris.value > 0)
14187 if (!rsurface.texture->currentlayers->depthmask)
14188 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14189 else if (ent == r_refdef.scene.worldentity)
14190 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14192 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14193 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14194 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14196 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14199 if (r_shownormals.value < 0)
14201 qglBegin(GL_LINES);
14202 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14204 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14205 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14206 qglVertex3f(v[0], v[1], v[2]);
14207 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14208 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14209 qglVertex3f(v[0], v[1], v[2]);
14214 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14216 qglBegin(GL_LINES);
14217 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14219 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14220 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14221 qglVertex3f(v[0], v[1], v[2]);
14222 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14223 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14224 qglVertex3f(v[0], v[1], v[2]);
14228 qglBegin(GL_LINES);
14229 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14231 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14232 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14233 qglVertex3f(v[0], v[1], v[2]);
14234 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14235 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14236 qglVertex3f(v[0], v[1], v[2]);
14240 qglBegin(GL_LINES);
14241 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14243 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14244 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14245 qglVertex3f(v[0], v[1], v[2]);
14246 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14247 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14248 qglVertex3f(v[0], v[1], v[2]);
14255 rsurface.texture = NULL;
14259 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14260 int r_maxsurfacelist = 0;
14261 const msurface_t **r_surfacelist = NULL;
14262 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14264 int i, j, endj, flagsmask;
14265 dp_model_t *model = r_refdef.scene.worldmodel;
14266 msurface_t *surfaces;
14267 unsigned char *update;
14268 int numsurfacelist = 0;
14272 if (r_maxsurfacelist < model->num_surfaces)
14274 r_maxsurfacelist = model->num_surfaces;
14276 Mem_Free((msurface_t**)r_surfacelist);
14277 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14280 RSurf_ActiveWorldEntity();
14282 surfaces = model->data_surfaces;
14283 update = model->brushq1.lightmapupdateflags;
14285 // update light styles on this submodel
14286 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14288 model_brush_lightstyleinfo_t *style;
14289 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14291 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14293 int *list = style->surfacelist;
14294 style->value = r_refdef.scene.lightstylevalue[style->style];
14295 for (j = 0;j < style->numsurfaces;j++)
14296 update[list[j]] = true;
14301 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14305 R_DrawDebugModel();
14306 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14310 rsurface.lightmaptexture = NULL;
14311 rsurface.deluxemaptexture = NULL;
14312 rsurface.uselightmaptexture = false;
14313 rsurface.texture = NULL;
14314 rsurface.rtlight = NULL;
14315 numsurfacelist = 0;
14316 // add visible surfaces to draw list
14317 for (i = 0;i < model->nummodelsurfaces;i++)
14319 j = model->sortedmodelsurfaces[i];
14320 if (r_refdef.viewcache.world_surfacevisible[j])
14321 r_surfacelist[numsurfacelist++] = surfaces + j;
14323 // update lightmaps if needed
14324 if (model->brushq1.firstrender)
14326 model->brushq1.firstrender = false;
14327 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14329 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14333 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14334 if (r_refdef.viewcache.world_surfacevisible[j])
14336 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14338 // don't do anything if there were no surfaces
14339 if (!numsurfacelist)
14341 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14344 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14345 GL_AlphaTest(false);
14347 // add to stats if desired
14348 if (r_speeds.integer && !skysurfaces && !depthonly)
14350 r_refdef.stats.world_surfaces += numsurfacelist;
14351 for (j = 0;j < numsurfacelist;j++)
14352 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14355 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14358 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14360 int i, j, endj, flagsmask;
14361 dp_model_t *model = ent->model;
14362 msurface_t *surfaces;
14363 unsigned char *update;
14364 int numsurfacelist = 0;
14368 if (r_maxsurfacelist < model->num_surfaces)
14370 r_maxsurfacelist = model->num_surfaces;
14372 Mem_Free((msurface_t **)r_surfacelist);
14373 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14376 // if the model is static it doesn't matter what value we give for
14377 // wantnormals and wanttangents, so this logic uses only rules applicable
14378 // to a model, knowing that they are meaningless otherwise
14379 if (ent == r_refdef.scene.worldentity)
14380 RSurf_ActiveWorldEntity();
14381 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14382 RSurf_ActiveModelEntity(ent, false, false, false);
14384 RSurf_ActiveModelEntity(ent, true, true, true);
14385 else if (depthonly)
14387 switch (vid.renderpath)
14389 case RENDERPATH_GL20:
14390 case RENDERPATH_CGGL:
14391 case RENDERPATH_D3D9:
14392 case RENDERPATH_D3D10:
14393 case RENDERPATH_D3D11:
14394 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14396 case RENDERPATH_GL13:
14397 case RENDERPATH_GL11:
14398 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14404 switch (vid.renderpath)
14406 case RENDERPATH_GL20:
14407 case RENDERPATH_CGGL:
14408 case RENDERPATH_D3D9:
14409 case RENDERPATH_D3D10:
14410 case RENDERPATH_D3D11:
14411 RSurf_ActiveModelEntity(ent, true, true, false);
14413 case RENDERPATH_GL13:
14414 case RENDERPATH_GL11:
14415 RSurf_ActiveModelEntity(ent, true, false, false);
14420 surfaces = model->data_surfaces;
14421 update = model->brushq1.lightmapupdateflags;
14423 // update light styles
14424 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14426 model_brush_lightstyleinfo_t *style;
14427 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14429 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14431 int *list = style->surfacelist;
14432 style->value = r_refdef.scene.lightstylevalue[style->style];
14433 for (j = 0;j < style->numsurfaces;j++)
14434 update[list[j]] = true;
14439 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14443 R_DrawDebugModel();
14444 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14448 rsurface.lightmaptexture = NULL;
14449 rsurface.deluxemaptexture = NULL;
14450 rsurface.uselightmaptexture = false;
14451 rsurface.texture = NULL;
14452 rsurface.rtlight = NULL;
14453 numsurfacelist = 0;
14454 // add visible surfaces to draw list
14455 for (i = 0;i < model->nummodelsurfaces;i++)
14456 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14457 // don't do anything if there were no surfaces
14458 if (!numsurfacelist)
14460 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14463 // update lightmaps if needed
14467 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14472 R_BuildLightMap(ent, surfaces + j);
14477 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14479 R_BuildLightMap(ent, surfaces + j);
14480 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14481 GL_AlphaTest(false);
14483 // add to stats if desired
14484 if (r_speeds.integer && !skysurfaces && !depthonly)
14486 r_refdef.stats.entities_surfaces += numsurfacelist;
14487 for (j = 0;j < numsurfacelist;j++)
14488 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14491 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14494 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14496 static texture_t texture;
14497 static msurface_t surface;
14498 const msurface_t *surfacelist = &surface;
14500 // fake enough texture and surface state to render this geometry
14502 texture.update_lastrenderframe = -1; // regenerate this texture
14503 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14504 texture.currentskinframe = skinframe;
14505 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14506 texture.offsetmapping = OFFSETMAPPING_OFF;
14507 texture.offsetscale = 1;
14508 texture.specularscalemod = 1;
14509 texture.specularpowermod = 1;
14511 surface.texture = &texture;
14512 surface.num_triangles = numtriangles;
14513 surface.num_firsttriangle = firsttriangle;
14514 surface.num_vertices = numvertices;
14515 surface.num_firstvertex = firstvertex;
14518 rsurface.texture = R_GetCurrentTexture(surface.texture);
14519 rsurface.lightmaptexture = NULL;
14520 rsurface.deluxemaptexture = NULL;
14521 rsurface.uselightmaptexture = false;
14522 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14525 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)
14527 static msurface_t surface;
14528 const msurface_t *surfacelist = &surface;
14530 // fake enough texture and surface state to render this geometry
14532 surface.texture = texture;
14533 surface.num_triangles = numtriangles;
14534 surface.num_firsttriangle = firsttriangle;
14535 surface.num_vertices = numvertices;
14536 surface.num_firstvertex = firstvertex;
14539 rsurface.texture = R_GetCurrentTexture(surface.texture);
14540 rsurface.lightmaptexture = NULL;
14541 rsurface.deluxemaptexture = NULL;
14542 rsurface.uselightmaptexture = false;
14543 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);