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 " // 2 sample offset mapping (only 2 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.5;\n"
1159 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1160 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1161 " return TexCoord;\n"
1164 "#endif // USEOFFSETMAPPING\n"
1166 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1167 "uniform sampler2D Texture_Attenuation;\n"
1168 "uniform samplerCube Texture_Cube;\n"
1171 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1173 "#ifdef USESHADOWMAP2D\n"
1174 "# ifdef USESHADOWSAMPLER\n"
1175 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1177 "uniform sampler2D Texture_ShadowMap2D;\n"
1181 "#ifdef USESHADOWMAPVSDCT\n"
1182 "uniform samplerCube Texture_CubeProjection;\n"
1185 "#if defined(USESHADOWMAP2D)\n"
1186 "uniform vec2 ShadowMap_TextureScale;\n"
1187 "uniform vec4 ShadowMap_Parameters;\n"
1190 "#if defined(USESHADOWMAP2D)\n"
1191 "# ifdef USESHADOWMAPORTHO\n"
1192 "# define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1194 "# ifdef USESHADOWMAPVSDCT\n"
1195 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1197 " vec3 adir = abs(dir);\n"
1198 " vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1199 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1200 " return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1203 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1205 " vec3 adir = abs(dir);\n"
1206 " float ma = adir.z;\n"
1207 " vec4 proj = vec4(dir, 2.5);\n"
1208 " if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1209 " if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1210 " vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1211 " 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"
1215 "#endif // defined(USESHADOWMAP2D)\n"
1217 "# ifdef USESHADOWMAP2D\n"
1218 "float ShadowMapCompare(vec3 dir)\n"
1220 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1223 "# ifdef USESHADOWSAMPLER\n"
1224 "# ifdef USESHADOWMAPPCF\n"
1225 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1226 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1227 " 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"
1229 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1232 "# ifdef USESHADOWMAPPCF\n"
1233 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1234 "# ifdef GL_ARB_texture_gather\n"
1235 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1237 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1239 " vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1240 "# if USESHADOWMAPPCF > 1\n"
1241 " vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1242 " vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1243 " vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1244 " vec4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
1245 " vec4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
1246 " vec4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
1247 " vec4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
1248 " vec4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
1249 " vec4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
1250 " vec4 locols = vec4(group1.ab, group3.ab);\n"
1251 " vec4 hicols = vec4(group7.rg, group9.rg);\n"
1252 " locols.yz += group2.ab;\n"
1253 " hicols.yz += group8.rg;\n"
1254 " vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1255 " vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1256 " mix(locols, hicols, offset.y);\n"
1257 " vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1258 " cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1259 " f = dot(cols, vec4(1.0/25.0));\n"
1261 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1262 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1263 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1264 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1265 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1266 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1267 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1270 "# ifdef GL_EXT_gpu_shader4\n"
1271 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1273 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1275 "# if USESHADOWMAPPCF > 1\n"
1276 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1277 " center *= ShadowMap_TextureScale;\n"
1278 " 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"
1279 " 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"
1280 " 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"
1281 " 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"
1282 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1283 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1285 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1286 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1287 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1288 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1289 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1290 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1294 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1297 "# ifdef USESHADOWMAPORTHO\n"
1298 " return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1304 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1305 "#endif // FRAGMENT_SHADER\n"
1310 "#ifdef MODE_DEFERREDGEOMETRY\n"
1311 "#ifdef VERTEX_SHADER\n"
1312 "uniform mat4 TexMatrix;\n"
1313 "#ifdef USEVERTEXTEXTUREBLEND\n"
1314 "uniform mat4 BackgroundTexMatrix;\n"
1316 "uniform mat4 ModelViewMatrix;\n"
1319 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1320 "#ifdef USEVERTEXTEXTUREBLEND\n"
1321 " gl_FrontColor = gl_Color;\n"
1322 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1325 " // transform unnormalized eye direction into tangent space\n"
1326 "#ifdef USEOFFSETMAPPING\n"
1327 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1328 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1329 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1330 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1333 " VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1334 " VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1335 " VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1336 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1338 "#endif // VERTEX_SHADER\n"
1340 "#ifdef FRAGMENT_SHADER\n"
1343 "#ifdef USEOFFSETMAPPING\n"
1344 " // apply offsetmapping\n"
1345 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1346 "#define TexCoord TexCoordOffset\n"
1349 "#ifdef USEALPHAKILL\n"
1350 " if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1354 "#ifdef USEVERTEXTEXTUREBLEND\n"
1355 " float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1356 " float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1357 " //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1358 " //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1361 "#ifdef USEVERTEXTEXTUREBLEND\n"
1362 " vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1363 " float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1365 " vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1366 " float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1369 " gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1371 "#endif // FRAGMENT_SHADER\n"
1372 "#else // !MODE_DEFERREDGEOMETRY\n"
1377 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1378 "#ifdef VERTEX_SHADER\n"
1379 "uniform mat4 ModelViewMatrix;\n"
1382 " ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1383 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1385 "#endif // VERTEX_SHADER\n"
1387 "#ifdef FRAGMENT_SHADER\n"
1388 "uniform mat4 ViewToLight;\n"
1389 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1390 "uniform vec2 ScreenToDepth;\n"
1391 "uniform myhalf3 DeferredColor_Ambient;\n"
1392 "uniform myhalf3 DeferredColor_Diffuse;\n"
1393 "#ifdef USESPECULAR\n"
1394 "uniform myhalf3 DeferredColor_Specular;\n"
1395 "uniform myhalf SpecularPower;\n"
1397 "uniform myhalf2 PixelToScreenTexCoord;\n"
1400 " // calculate viewspace pixel position\n"
1401 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1403 " position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1404 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1405 " // decode viewspace pixel normal\n"
1406 " myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1407 " myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1408 " // surfacenormal = pixel normal in viewspace\n"
1409 " // LightVector = pixel to light in viewspace\n"
1410 " // CubeVector = position in lightspace\n"
1411 " // eyevector = pixel to view in viewspace\n"
1412 " vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1413 " myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1414 "#ifdef USEDIFFUSE\n"
1415 " // calculate diffuse shading\n"
1416 " myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1417 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1419 "#ifdef USESPECULAR\n"
1420 " // calculate directional shading\n"
1421 " vec3 eyevector = position * -1.0;\n"
1422 "# ifdef USEEXACTSPECULARMATH\n"
1423 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1425 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1426 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1430 "#if defined(USESHADOWMAP2D)\n"
1431 " fade *= ShadowMapCompare(CubeVector);\n"
1434 "#ifdef USEDIFFUSE\n"
1435 " gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1437 " gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1439 "#ifdef USESPECULAR\n"
1440 " gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1442 " gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1445 "# ifdef USECUBEFILTER\n"
1446 " vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1447 " gl_FragData[0].rgb *= cubecolor;\n"
1448 " gl_FragData[1].rgb *= cubecolor;\n"
1451 "#endif // FRAGMENT_SHADER\n"
1452 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1457 "#ifdef VERTEX_SHADER\n"
1458 "uniform mat4 TexMatrix;\n"
1459 "#ifdef USEVERTEXTEXTUREBLEND\n"
1460 "uniform mat4 BackgroundTexMatrix;\n"
1462 "#ifdef MODE_LIGHTSOURCE\n"
1463 "uniform mat4 ModelToLight;\n"
1465 "#ifdef USESHADOWMAPORTHO\n"
1466 "uniform mat4 ShadowMapMatrix;\n"
1470 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1471 " gl_FrontColor = gl_Color;\n"
1473 " // copy the surface texcoord\n"
1474 " TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1475 "#ifdef USEVERTEXTEXTUREBLEND\n"
1476 " TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1478 "#ifdef USELIGHTMAP\n"
1479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1482 "#ifdef MODE_LIGHTSOURCE\n"
1483 " // transform vertex position into light attenuation/cubemap space\n"
1484 " // (-1 to +1 across the light box)\n"
1485 " CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1487 "# ifdef USEDIFFUSE\n"
1488 " // transform unnormalized light direction into tangent space\n"
1489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
1490 " // normalize it per pixel)\n"
1491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1498 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1499 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1500 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1501 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1504 " // transform unnormalized eye direction into tangent space\n"
1505 "#ifdef USEEYEVECTOR\n"
1506 " vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1507 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1508 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1509 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1513 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1514 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1517 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1518 " VectorS = gl_MultiTexCoord1.xyz;\n"
1519 " VectorT = gl_MultiTexCoord2.xyz;\n"
1520 " VectorR = gl_MultiTexCoord3.xyz;\n"
1523 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1524 " gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1526 "#ifdef USESHADOWMAPORTHO\n"
1527 " ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1530 "#ifdef USEREFLECTION\n"
1531 " ModelViewProjectionPosition = gl_Position;\n"
1534 "#endif // VERTEX_SHADER\n"
1539 "#ifdef FRAGMENT_SHADER\n"
1540 "#ifdef USEDEFERREDLIGHTMAP\n"
1541 "uniform myhalf2 PixelToScreenTexCoord;\n"
1542 "uniform myhalf3 DeferredMod_Diffuse;\n"
1543 "uniform myhalf3 DeferredMod_Specular;\n"
1545 "uniform myhalf3 Color_Ambient;\n"
1546 "uniform myhalf3 Color_Diffuse;\n"
1547 "uniform myhalf3 Color_Specular;\n"
1548 "uniform myhalf SpecularPower;\n"
1550 "uniform myhalf3 Color_Glow;\n"
1552 "uniform myhalf Alpha;\n"
1553 "#ifdef USEREFLECTION\n"
1554 "uniform vec4 DistortScaleRefractReflect;\n"
1555 "uniform vec4 ScreenScaleRefractReflect;\n"
1556 "uniform vec4 ScreenCenterRefractReflect;\n"
1557 "uniform myhalf4 ReflectColor;\n"
1559 "#ifdef USEREFLECTCUBE\n"
1560 "uniform mat4 ModelToReflectCube;\n"
1561 "uniform sampler2D Texture_ReflectMask;\n"
1562 "uniform samplerCube Texture_ReflectCube;\n"
1564 "#ifdef MODE_LIGHTDIRECTION\n"
1565 "uniform myhalf3 LightColor;\n"
1567 "#ifdef MODE_LIGHTSOURCE\n"
1568 "uniform myhalf3 LightColor;\n"
1572 "#ifdef USEOFFSETMAPPING\n"
1573 " // apply offsetmapping\n"
1574 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1575 "#define TexCoord TexCoordOffset\n"
1578 " // combine the diffuse textures (base, pants, shirt)\n"
1579 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1580 "#ifdef USEALPHAKILL\n"
1581 " if (color.a < 0.5)\n"
1584 " color.a *= Alpha;\n"
1585 "#ifdef USECOLORMAPPING\n"
1586 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1588 "#ifdef USEVERTEXTEXTUREBLEND\n"
1589 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1590 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1591 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1592 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1594 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1597 " // get the surface normal\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1601 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1604 " // get the material colors\n"
1605 " myhalf3 diffusetex = color.rgb;\n"
1606 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1607 "# ifdef USEVERTEXTEXTUREBLEND\n"
1608 " myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1610 " myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1614 "#ifdef USEREFLECTCUBE\n"
1615 " vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1616 " vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1617 " vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1618 " diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1624 "#ifdef MODE_LIGHTSOURCE\n"
1625 " // light source\n"
1626 "#ifdef USEDIFFUSE\n"
1627 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1628 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1629 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1630 "#ifdef USESPECULAR\n"
1631 "#ifdef USEEXACTSPECULARMATH\n"
1632 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1634 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1635 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1637 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1640 " color.rgb = diffusetex * Color_Ambient;\n"
1642 " color.rgb *= LightColor;\n"
1643 " color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1644 "#if defined(USESHADOWMAP2D)\n"
1645 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1647 "# ifdef USECUBEFILTER\n"
1648 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1650 "#endif // MODE_LIGHTSOURCE\n"
1655 "#ifdef MODE_LIGHTDIRECTION\n"
1657 "#ifdef USEDIFFUSE\n"
1658 " myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1660 "#define lightcolor LightColor\n"
1661 "#endif // MODE_LIGHTDIRECTION\n"
1662 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1664 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1665 " myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1666 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1667 " // convert modelspace light vector to tangentspace\n"
1668 " myhalf3 lightnormal;\n"
1669 " lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1670 " lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1671 " lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1672 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1673 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1674 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1675 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1676 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1677 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1678 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1679 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1680 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1681 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1682 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1683 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1685 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1686 " myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1687 " myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1693 "#ifdef MODE_FAKELIGHT\n"
1695 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1696 "myhalf3 lightcolor = myhalf3(1.0);\n"
1697 "#endif // MODE_FAKELIGHT\n"
1702 "#ifdef MODE_LIGHTMAP\n"
1703 " color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1704 "#endif // MODE_LIGHTMAP\n"
1705 "#ifdef MODE_VERTEXCOLOR\n"
1706 " color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1707 "#endif // MODE_VERTEXCOLOR\n"
1708 "#ifdef MODE_FLATCOLOR\n"
1709 " color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif // MODE_FLATCOLOR\n"
1716 "# ifdef USEDIFFUSE\n"
1717 " myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1718 "# ifdef USESPECULAR\n"
1719 "# ifdef USEEXACTSPECULARMATH\n"
1720 " myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1722 " myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1723 " myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1725 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1727 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1730 " color.rgb = diffusetex * Color_Ambient;\n"
1734 "#ifdef USESHADOWMAPORTHO\n"
1735 " color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1738 "#ifdef USEDEFERREDLIGHTMAP\n"
1739 " vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1740 " color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1741 " color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1745 "#ifdef USEVERTEXTEXTUREBLEND\n"
1746 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1748 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1753 " color.rgb = FogVertex(color.rgb);\n"
1756 " // 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"
1757 "#ifdef USEREFLECTION\n"
1758 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1759 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1760 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1761 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1762 " // FIXME temporary hack to detect the case that the reflection\n"
1763 " // gets blackened at edges due to leaving the area that contains actual\n"
1765 " // Remove this 'ack once we have a better way to stop this thing from\n"
1767 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1768 " 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 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1772 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1775 " gl_FragColor = vec4(color);\n"
1777 "#endif // FRAGMENT_SHADER\n"
1779 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1780 "#endif // !MODE_DEFERREDGEOMETRY\n"
1781 "#endif // !MODE_WATER\n"
1782 "#endif // !MODE_REFRACTION\n"
1783 "#endif // !MODE_BLOOMBLUR\n"
1784 "#endif // !MODE_GENERIC\n"
1785 "#endif // !MODE_POSTPROCESS\n"
1786 "#endif // !MODE_SHOWDEPTH\n"
1787 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1791 =========================================================================================================================================================
1795 =========================================================================================================================================================
1799 =========================================================================================================================================================
1803 =========================================================================================================================================================
1807 =========================================================================================================================================================
1811 =========================================================================================================================================================
1815 =========================================================================================================================================================
1818 const char *builtincgshaderstring =
1819 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1820 "// written by Forest 'LordHavoc' Hale\n"
1821 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1823 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1824 "#if defined(USEREFLECTION)\n"
1825 "#undef USESHADOWMAPORTHO\n"
1828 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1831 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1832 "#define USELIGHTMAP\n"
1834 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1835 "#define USEEYEVECTOR\n"
1838 "#ifdef FRAGMENT_SHADER\n"
1840 "//#undef USESHADOWMAPPCF\n"
1841 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1842 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1844 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1848 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1849 "#ifdef VERTEX_SHADER\n"
1852 "float4 gl_Vertex : POSITION,\n"
1853 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1854 "out float4 gl_Position : POSITION,\n"
1855 "out float Depth : TEXCOORD0\n"
1858 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1859 " Depth = gl_Position.z;\n"
1863 "#ifdef FRAGMENT_SHADER\n"
1866 "float Depth : TEXCOORD0,\n"
1867 "out float4 gl_FragColor : COLOR\n"
1870 "// float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1871 " float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1872 " temp.yz -= floor(temp.yz);\n"
1873 " gl_FragColor = temp;\n"
1874 "// gl_FragColor = float4(Depth,0,0,0);\n"
1877 "#else // !MODE_DEPTH_ORSHADOW\n"
1882 "#ifdef MODE_SHOWDEPTH\n"
1883 "#ifdef VERTEX_SHADER\n"
1886 "float4 gl_Vertex : POSITION,\n"
1887 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1888 "out float4 gl_Position : POSITION,\n"
1889 "out float4 gl_FrontColor : COLOR0\n"
1892 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1893 " gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1897 "#ifdef FRAGMENT_SHADER\n"
1900 "float4 gl_FrontColor : COLOR0,\n"
1901 "out float4 gl_FragColor : COLOR\n"
1904 " gl_FragColor = gl_FrontColor;\n"
1907 "#else // !MODE_SHOWDEPTH\n"
1912 "#ifdef MODE_POSTPROCESS\n"
1914 "#ifdef VERTEX_SHADER\n"
1917 "float4 gl_Vertex : POSITION,\n"
1918 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1919 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1920 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float2 TexCoord1 : TEXCOORD0,\n"
1923 "out float2 TexCoord2 : TEXCOORD1\n"
1926 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1927 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
1929 " TexCoord2 = gl_MultiTexCoord4.xy;\n"
1934 "#ifdef FRAGMENT_SHADER\n"
1937 "float2 TexCoord1 : TEXCOORD0,\n"
1938 "float2 TexCoord2 : TEXCOORD1,\n"
1939 "uniform sampler Texture_First : register(s0),\n"
1941 "uniform sampler Texture_Second : register(s1),\n"
1943 "#ifdef USEGAMMARAMPS\n"
1944 "uniform sampler Texture_GammaRamps : register(s2),\n"
1946 "#ifdef USESATURATION\n"
1947 "uniform float Saturation : register(c30),\n"
1949 "#ifdef USEVIEWTINT\n"
1950 "uniform float4 ViewTintColor : register(c41),\n"
1952 "uniform float4 UserVec1 : register(c37),\n"
1953 "uniform float4 UserVec2 : register(c38),\n"
1954 "uniform float4 UserVec3 : register(c39),\n"
1955 "uniform float4 UserVec4 : register(c40),\n"
1956 "uniform float ClientTime : register(c2),\n"
1957 "uniform float2 PixelSize : register(c25),\n"
1958 "uniform float4 BloomColorSubtract : register(c43),\n"
1959 "out float4 gl_FragColor : COLOR\n"
1962 " gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1964 " gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1966 "#ifdef USEVIEWTINT\n"
1967 " gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1970 "#ifdef USEPOSTPROCESSING\n"
1971 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1972 "// 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"
1973 " float sobel = 1.0;\n"
1974 " // float2 ts = textureSize(Texture_First, 0);\n"
1975 " // float2 px = float2(1/ts.x, 1/ts.y);\n"
1976 " float2 px = PixelSize;\n"
1977 " float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1978 " float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x, 0.0)).rgb;\n"
1979 " float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1980 " float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1981 " float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x, 0.0)).rgb;\n"
1982 " float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1983 " float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1984 " float3 y2 = tex2D(Texture_First, TexCoord1 + float2( 0.0,-px.y)).rgb;\n"
1985 " float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1986 " float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1987 " float3 y5 = tex2D(Texture_First, TexCoord1 + float2( 0.0, px.y)).rgb;\n"
1988 " float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 " float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1990 " float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1991 " float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1992 " float px4 = 1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1993 " float px5 = 2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1994 " float px6 = 1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1995 " float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1996 " float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1997 " float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1998 " float py4 = 1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1999 " float py5 = 2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2000 " float py6 = 1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2001 " sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2002 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2003 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2004 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2005 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107, 0.707107)) * UserVec1.y;\n"
2006 " gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990, 0.891007)) * UserVec1.y;\n"
2007 " gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2008 " gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2011 "#ifdef USESATURATION\n"
2012 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2013 " float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2014 " // 'vampire sight' effect, wheres red is compensated\n"
2015 " #ifdef SATURATION_REDCOMPENSATE\n"
2016 " float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2017 " gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2018 " gl_FragColor.r += r;\n"
2020 " // normal desaturation\n"
2021 " //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2022 " gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2026 "#ifdef USEGAMMARAMPS\n"
2027 " gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2028 " gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2029 " gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2033 "#else // !MODE_POSTPROCESS\n"
2038 "#ifdef MODE_GENERIC\n"
2039 "#ifdef VERTEX_SHADER\n"
2042 "float4 gl_Vertex : POSITION,\n"
2043 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2044 "float4 gl_Color : COLOR0,\n"
2045 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2046 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2047 "out float4 gl_Position : POSITION,\n"
2048 "#ifdef USEDIFFUSE\n"
2049 "out float2 TexCoord1 : TEXCOORD0,\n"
2051 "#ifdef USESPECULAR\n"
2052 "out float2 TexCoord2 : TEXCOORD1,\n"
2054 "out float4 gl_FrontColor : COLOR\n"
2058 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2060 " gl_FrontColor = gl_Color; // Cg is forward\n"
2062 "#ifdef USEDIFFUSE\n"
2063 " TexCoord1 = gl_MultiTexCoord0.xy;\n"
2065 "#ifdef USESPECULAR\n"
2066 " TexCoord2 = gl_MultiTexCoord1.xy;\n"
2068 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2072 "#ifdef FRAGMENT_SHADER\n"
2076 "float4 gl_FrontColor : COLOR0,\n"
2077 "float2 TexCoord1 : TEXCOORD0,\n"
2078 "float2 TexCoord2 : TEXCOORD1,\n"
2079 "#ifdef USEDIFFUSE\n"
2080 "uniform sampler Texture_First : register(s0),\n"
2082 "#ifdef USESPECULAR\n"
2083 "uniform sampler Texture_Second : register(s1),\n"
2085 "out float4 gl_FragColor : COLOR\n"
2088 " gl_FragColor = gl_FrontColor;\n"
2089 "#ifdef USEDIFFUSE\n"
2090 " gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2093 "#ifdef USESPECULAR\n"
2094 " float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2095 "# ifdef USECOLORMAPPING\n"
2096 " gl_FragColor *= tex2;\n"
2099 " gl_FragColor += tex2;\n"
2101 "# ifdef USEVERTEXTEXTUREBLEND\n"
2102 " gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2107 "#else // !MODE_GENERIC\n"
2112 "#ifdef MODE_BLOOMBLUR\n"
2113 "#ifdef VERTEX_SHADER\n"
2116 "float4 gl_Vertex : POSITION,\n"
2117 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2118 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2119 "out float4 gl_Position : POSITION,\n"
2120 "out float2 TexCoord : TEXCOORD0\n"
2123 " TexCoord = gl_MultiTexCoord0.xy;\n"
2124 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2128 "#ifdef FRAGMENT_SHADER\n"
2132 "float2 TexCoord : TEXCOORD0,\n"
2133 "uniform sampler Texture_First : register(s0),\n"
2134 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2135 "out float4 gl_FragColor : COLOR\n"
2139 " float2 tc = TexCoord;\n"
2140 " float3 color = tex2D(Texture_First, tc).rgb;\n"
2141 " tc += BloomBlur_Parameters.xy;\n"
2142 " for (i = 1;i < SAMPLES;i++)\n"
2144 " color += tex2D(Texture_First, tc).rgb;\n"
2145 " tc += BloomBlur_Parameters.xy;\n"
2147 " gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2150 "#else // !MODE_BLOOMBLUR\n"
2151 "#ifdef MODE_REFRACTION\n"
2152 "#ifdef VERTEX_SHADER\n"
2155 "float4 gl_Vertex : POSITION,\n"
2156 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2157 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2158 "uniform float4x4 TexMatrix : register(c0),\n"
2159 "uniform float3 EyePosition : register(c24),\n"
2160 "out float4 gl_Position : POSITION,\n"
2161 "out float2 TexCoord : TEXCOORD0,\n"
2162 "out float3 EyeVector : TEXCOORD1,\n"
2163 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2166 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2167 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2168 " ModelViewProjectionPosition = gl_Position;\n"
2172 "#ifdef FRAGMENT_SHADER\n"
2175 "float2 TexCoord : TEXCOORD0,\n"
2176 "float3 EyeVector : TEXCOORD1,\n"
2177 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2178 "uniform sampler Texture_Normal : register(s0),\n"
2179 "uniform sampler Texture_Refraction : register(s3),\n"
2180 "uniform sampler Texture_Reflection : register(s7),\n"
2181 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2182 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2183 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2184 "uniform float4 RefractColor : register(c29),\n"
2185 "out float4 gl_FragColor : COLOR\n"
2188 " float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2189 " //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"
2190 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2191 " float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2192 " // FIXME temporary hack to detect the case that the reflection\n"
2193 " // gets blackened at edges due to leaving the area that contains actual\n"
2195 " // Remove this 'ack once we have a better way to stop this thing from\n"
2197 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2198 " 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 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2202 " gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2205 "#else // !MODE_REFRACTION\n"
2210 "#ifdef MODE_WATER\n"
2211 "#ifdef VERTEX_SHADER\n"
2215 "float4 gl_Vertex : POSITION,\n"
2216 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2217 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2218 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2219 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2220 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2221 "uniform float4x4 TexMatrix : register(c0),\n"
2222 "uniform float3 EyePosition : register(c24),\n"
2223 "out float4 gl_Position : POSITION,\n"
2224 "out float2 TexCoord : TEXCOORD0,\n"
2225 "out float3 EyeVector : TEXCOORD1,\n"
2226 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2229 " TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2230 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2231 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2232 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2233 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2234 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2235 " ModelViewProjectionPosition = gl_Position;\n"
2239 "#ifdef FRAGMENT_SHADER\n"
2242 "float2 TexCoord : TEXCOORD0,\n"
2243 "float3 EyeVector : TEXCOORD1,\n"
2244 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2245 "uniform sampler Texture_Normal : register(s0),\n"
2246 "uniform sampler Texture_Refraction : register(s3),\n"
2247 "uniform sampler Texture_Reflection : register(s7),\n"
2248 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2249 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2250 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2251 "uniform float4 RefractColor : register(c29),\n"
2252 "uniform float4 ReflectColor : register(c26),\n"
2253 "uniform float ReflectFactor : register(c27),\n"
2254 "uniform float ReflectOffset : register(c28),\n"
2255 "out float4 gl_FragColor : COLOR\n"
2258 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2259 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2260 " float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2261 " //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2262 " float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2263 " // FIXME temporary hack to detect the case that the reflection\n"
2264 " // gets blackened at edges due to leaving the area that contains actual\n"
2266 " // Remove this 'ack once we have a better way to stop this thing from\n"
2268 " float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2269 " 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 " ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2273 " f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\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 " ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2278 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2279 " gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2282 "#else // !MODE_WATER\n"
2287 "// 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"
2289 "// fragment shader specific:\n"
2290 "#ifdef FRAGMENT_SHADER\n"
2293 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2296 "#ifdef USEFOGHEIGHTTEXTURE\n"
2297 " float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2298 " fogfrac = fogheightpixel.a;\n"
2299 " return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2301 "# ifdef USEFOGOUTSIDE\n"
2302 " fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2304 " fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2306 " return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2311 "#ifdef USEOFFSETMAPPING\n"
2312 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2314 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2315 " // 14 sample relief mapping: linear search and then binary search\n"
2316 " // this basically steps forward a small amount repeatedly until it finds\n"
2317 " // itself inside solid, then jitters forward and back using decreasing\n"
2318 " // amounts to find the impact\n"
2319 " //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2320 " //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2321 " float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2322 " float3 RT = float3(TexCoord, 1);\n"
2323 " OffsetVector *= 0.1;\n"
2324 " RT += OffsetVector * step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
2334 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
2335 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
2336 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
2337 " RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2340 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2341 " // this basically moves forward the full distance, and then backs up based\n"
2342 " // on height of samples\n"
2343 " //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2344 " //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2345 " float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2346 " TexCoord += OffsetVector;\n"
2347 " OffsetVector *= 0.333;\n"
2348 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2349 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2350 " TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2351 " return TexCoord;\n"
2354 "#endif // USEOFFSETMAPPING\n"
2356 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2357 "#if defined(USESHADOWMAP2D)\n"
2358 "# ifdef USESHADOWMAPORTHO\n"
2359 "# define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2361 "# ifdef USESHADOWMAPVSDCT\n"
2362 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2364 " float3 adir = abs(dir);\n"
2365 " float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2366 " float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2367 " return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2370 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2372 " float3 adir = abs(dir);\n"
2373 " float ma = adir.z;\n"
2374 " float4 proj = float4(dir, 2.5);\n"
2375 " if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2376 " if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2378 " 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"
2380 " float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2381 " 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"
2386 "#endif // defined(USESHADOWMAP2D)\n"
2388 "# ifdef USESHADOWMAP2D\n"
2389 "#ifdef USESHADOWMAPVSDCT\n"
2390 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2392 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2395 "#ifdef USESHADOWMAPVSDCT\n"
2396 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2398 " float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2402 "# ifdef USESHADOWSAMPLER\n"
2403 "# ifdef USESHADOWMAPPCF\n"
2404 "# define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r \n"
2405 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2406 " 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"
2408 " f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2411 "# ifdef USESHADOWMAPPCF\n"
2412 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2413 "# ifdef GL_ARB_texture_gather\n"
2414 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2416 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2418 " float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2419 "# if USESHADOWMAPPCF > 1\n"
2420 " float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2421 " float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2422 " float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2423 " float4 group4 = step(shadowmaptc.z, texval(-2.0, 0.0));\n"
2424 " float4 group5 = step(shadowmaptc.z, texval( 0.0, 0.0));\n"
2425 " float4 group6 = step(shadowmaptc.z, texval( 2.0, 0.0));\n"
2426 " float4 group7 = step(shadowmaptc.z, texval(-2.0, 2.0));\n"
2427 " float4 group8 = step(shadowmaptc.z, texval( 0.0, 2.0));\n"
2428 " float4 group9 = step(shadowmaptc.z, texval( 2.0, 2.0));\n"
2429 " float4 locols = float4(group1.ab, group3.ab);\n"
2430 " float4 hicols = float4(group7.rg, group9.rg);\n"
2431 " locols.yz += group2.ab;\n"
2432 " hicols.yz += group8.rg;\n"
2433 " float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2434 " float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2435 " lerp(locols, hicols, offset.y);\n"
2436 " float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2437 " cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2438 " f = dot(cols, float4(1.0/25.0));\n"
2440 " float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2441 " float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2442 " float4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
2443 " float4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
2444 " float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2445 " lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2446 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2449 "# ifdef GL_EXT_gpu_shader4\n"
2450 "# define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2452 "# define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r \n"
2454 "# if USESHADOWMAPPCF > 1\n"
2455 " float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2456 " center *= ShadowMap_TextureScale;\n"
2457 " 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"
2458 " 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"
2459 " 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"
2460 " 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"
2461 " float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2462 " f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2464 " float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2465 " float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2466 " float3 row2 = step(shadowmaptc.z, float3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
2467 " float3 row3 = step(shadowmaptc.z, float3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
2468 " float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2469 " f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2473 " f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2476 "# ifdef USESHADOWMAPORTHO\n"
2477 " return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2483 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2484 "#endif // FRAGMENT_SHADER\n"
2489 "#ifdef MODE_DEFERREDGEOMETRY\n"
2490 "#ifdef VERTEX_SHADER\n"
2493 "float4 gl_Vertex : POSITION,\n"
2494 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2495 "#ifdef USEVERTEXTEXTUREBLEND\n"
2496 "float4 gl_Color : COLOR0,\n"
2498 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2499 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2500 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2501 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2502 "uniform float4x4 TexMatrix : register(c0),\n"
2503 "#ifdef USEVERTEXTEXTUREBLEND\n"
2504 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2506 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2507 "#ifdef USEOFFSETMAPPING\n"
2508 "uniform float3 EyePosition : register(c24),\n"
2510 "out float4 gl_Position : POSITION,\n"
2511 "#ifdef USEVERTEXTEXTUREBLEND\n"
2512 "out float4 gl_FrontColor : COLOR,\n"
2514 "out float4 TexCoordBoth : TEXCOORD0,\n"
2515 "#ifdef USEOFFSETMAPPING\n"
2516 "out float3 EyeVector : TEXCOORD2,\n"
2518 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2519 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2520 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2523 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2524 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2528 " gl_FrontColor = gl_Color; // Cg is forward\n"
2530 " TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2533 " // transform unnormalized eye direction into tangent space\n"
2534 "#ifdef USEOFFSETMAPPING\n"
2535 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2536 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2537 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2538 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2541 " VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2542 " VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2543 " VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2544 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2545 " VectorR.w = gl_Position.z;\n"
2547 "#endif // VERTEX_SHADER\n"
2549 "#ifdef FRAGMENT_SHADER\n"
2552 "float4 TexCoordBoth : TEXCOORD0,\n"
2553 "float3 EyeVector : TEXCOORD2,\n"
2554 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2555 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2556 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2557 "uniform sampler Texture_Normal : register(s0),\n"
2558 "#ifdef USEALPHAKILL\n"
2559 "uniform sampler Texture_Color : register(s1),\n"
2561 "uniform sampler Texture_Gloss : register(s2),\n"
2562 "#ifdef USEVERTEXTEXTUREBLEND\n"
2563 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2564 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2566 "#ifdef USEOFFSETMAPPING\n"
2567 "uniform float OffsetMapping_Scale : register(c24),\n"
2569 "uniform half SpecularPower : register(c36),\n"
2571 "out float4 gl_FragData0 : COLOR0,\n"
2572 "out float4 gl_FragData1 : COLOR1\n"
2574 "out float4 gl_FragColor : COLOR\n"
2578 " float2 TexCoord = TexCoordBoth.xy;\n"
2579 "#ifdef USEOFFSETMAPPING\n"
2580 " // apply offsetmapping\n"
2581 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2582 "#define TexCoord TexCoordOffset\n"
2585 "#ifdef USEALPHAKILL\n"
2586 " if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2590 "#ifdef USEVERTEXTEXTUREBLEND\n"
2591 " float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2592 " float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2593 " //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2594 " //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2597 "#ifdef USEVERTEXTEXTUREBLEND\n"
2598 " float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2599 " float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2601 " float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2602 " float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2606 " 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"
2607 " float Depth = VectorR.w / 256.0;\n"
2608 " float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2609 "// float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2610 " depthcolor.yz -= floor(depthcolor.yz);\n"
2611 " gl_FragData1 = depthcolor;\n"
2613 " gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2616 "#endif // FRAGMENT_SHADER\n"
2617 "#else // !MODE_DEFERREDGEOMETRY\n"
2622 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2623 "#ifdef VERTEX_SHADER\n"
2626 "float4 gl_Vertex : POSITION,\n"
2627 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2628 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2629 "out float4 gl_Position : POSITION,\n"
2630 "out float4 ModelViewPosition : TEXCOORD0\n"
2633 " ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2634 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2636 "#endif // VERTEX_SHADER\n"
2638 "#ifdef FRAGMENT_SHADER\n"
2642 "float2 Pixel : VPOS,\n"
2644 "float2 Pixel : WPOS,\n"
2646 "float4 ModelViewPosition : TEXCOORD0,\n"
2647 "uniform float4x4 ViewToLight : register(c44),\n"
2648 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2649 "uniform float3 LightPosition : register(c23),\n"
2650 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2651 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2652 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2653 "#ifdef USESPECULAR\n"
2654 "uniform half3 DeferredColor_Specular : register(c11),\n"
2655 "uniform half SpecularPower : register(c36),\n"
2657 "uniform sampler Texture_Attenuation : register(s9),\n"
2658 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2659 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2661 "#ifdef USECUBEFILTER\n"
2662 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2665 "#ifdef USESHADOWMAP2D\n"
2666 "# ifdef USESHADOWSAMPLER\n"
2667 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2669 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2673 "#ifdef USESHADOWMAPVSDCT\n"
2674 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2677 "#if defined(USESHADOWMAP2D)\n"
2678 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2679 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2682 "out float4 gl_FragData0 : COLOR0,\n"
2683 "out float4 gl_FragData1 : COLOR1\n"
2686 " // calculate viewspace pixel position\n"
2687 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2688 " //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2689 " float3 position;\n"
2691 " position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2693 " position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2695 " position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2696 " // decode viewspace pixel normal\n"
2697 " half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2698 " half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2699 " // surfacenormal = pixel normal in viewspace\n"
2700 " // LightVector = pixel to light in viewspace\n"
2701 " // CubeVector = position in lightspace\n"
2702 " // eyevector = pixel to view in viewspace\n"
2703 " float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2704 " half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2705 "#ifdef USEDIFFUSE\n"
2706 " // calculate diffuse shading\n"
2707 " half3 lightnormal = half3(normalize(LightPosition - position));\n"
2708 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2710 "#ifdef USESPECULAR\n"
2711 " // calculate directional shading\n"
2712 " float3 eyevector = position * -1.0;\n"
2713 "# ifdef USEEXACTSPECULARMATH\n"
2714 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2716 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2717 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2721 "#if defined(USESHADOWMAP2D)\n"
2722 " fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2723 "#ifdef USESHADOWMAPVSDCT\n"
2724 ", Texture_CubeProjection\n"
2729 "#ifdef USEDIFFUSE\n"
2730 " gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2732 " gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2734 "#ifdef USESPECULAR\n"
2735 " gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2737 " gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2740 "# ifdef USECUBEFILTER\n"
2741 " float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2742 " gl_FragData0.rgb *= cubecolor;\n"
2743 " gl_FragData1.rgb *= cubecolor;\n"
2746 "#endif // FRAGMENT_SHADER\n"
2747 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2752 "#ifdef VERTEX_SHADER\n"
2755 "float4 gl_Vertex : POSITION,\n"
2756 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2757 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2758 "float4 gl_Color : COLOR0,\n"
2760 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2761 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2762 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2763 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2764 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2766 "uniform float3 EyePosition : register(c24),\n"
2767 "uniform float4x4 TexMatrix : register(c0),\n"
2768 "#ifdef USEVERTEXTEXTUREBLEND\n"
2769 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2771 "#ifdef MODE_LIGHTSOURCE\n"
2772 "uniform float4x4 ModelToLight : register(c20),\n"
2774 "#ifdef MODE_LIGHTSOURCE\n"
2775 "uniform float3 LightPosition : register(c27),\n"
2777 "#ifdef MODE_LIGHTDIRECTION\n"
2778 "uniform float3 LightDir : register(c26),\n"
2780 "uniform float4 FogPlane : register(c25),\n"
2781 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2782 "uniform float3 LightPosition : register(c27),\n"
2784 "#ifdef USESHADOWMAPORTHO\n"
2785 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2787 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2788 "out float4 gl_FrontColor : COLOR,\n"
2790 "out float4 TexCoordBoth : TEXCOORD0,\n"
2791 "#ifdef USELIGHTMAP\n"
2792 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2794 "#ifdef USEEYEVECTOR\n"
2795 "out float3 EyeVector : TEXCOORD2,\n"
2797 "#ifdef USEREFLECTION\n"
2798 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2801 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2803 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2804 "out float3 LightVector : TEXCOORD1,\n"
2806 "#ifdef MODE_LIGHTSOURCE\n"
2807 "out float3 CubeVector : TEXCOORD3,\n"
2809 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2810 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2811 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2812 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2814 "#ifdef USESHADOWMAPORTHO\n"
2815 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2817 "out float4 gl_Position : POSITION\n"
2820 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2822 " gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2824 " gl_FrontColor = gl_Color; // Cg is forward\n"
2827 " // copy the surface texcoord\n"
2828 " TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2829 "#ifdef USEVERTEXTEXTUREBLEND\n"
2830 " TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2832 "#ifdef USELIGHTMAP\n"
2833 " TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2836 "#ifdef MODE_LIGHTSOURCE\n"
2837 " // transform vertex position into light attenuation/cubemap space\n"
2838 " // (-1 to +1 across the light box)\n"
2839 " CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2841 "# ifdef USEDIFFUSE\n"
2842 " // transform unnormalized light direction into tangent space\n"
2843 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
2844 " // normalize it per pixel)\n"
2845 " float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2846 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2847 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2848 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2852 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2853 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2854 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2855 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2858 " // transform unnormalized eye direction into tangent space\n"
2859 "#ifdef USEEYEVECTOR\n"
2860 " float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2861 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2862 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2863 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2867 " EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2868 " EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2871 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2872 " VectorS = gl_MultiTexCoord1.xyz;\n"
2873 " VectorT = gl_MultiTexCoord2.xyz;\n"
2874 " VectorR = gl_MultiTexCoord3.xyz;\n"
2877 " // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2878 " gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2880 "#ifdef USESHADOWMAPORTHO\n"
2881 " ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2884 "#ifdef USEREFLECTION\n"
2885 " ModelViewProjectionPosition = gl_Position;\n"
2888 "#endif // VERTEX_SHADER\n"
2893 "#ifdef FRAGMENT_SHADER\n"
2896 "#ifdef USEDEFERREDLIGHTMAP\n"
2898 "float2 Pixel : VPOS,\n"
2900 "float2 Pixel : WPOS,\n"
2903 "float4 gl_FrontColor : COLOR,\n"
2904 "float4 TexCoordBoth : TEXCOORD0,\n"
2905 "#ifdef USELIGHTMAP\n"
2906 "float2 TexCoordLightmap : TEXCOORD1,\n"
2908 "#ifdef USEEYEVECTOR\n"
2909 "float3 EyeVector : TEXCOORD2,\n"
2911 "#ifdef USEREFLECTION\n"
2912 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2915 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2917 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2918 "float3 LightVector : TEXCOORD1,\n"
2920 "#ifdef MODE_LIGHTSOURCE\n"
2921 "float3 CubeVector : TEXCOORD3,\n"
2923 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2924 "float4 ModelViewPosition : TEXCOORD0,\n"
2926 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2927 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2928 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2929 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2931 "#ifdef USESHADOWMAPORTHO\n"
2932 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2935 "uniform sampler Texture_Normal : register(s0),\n"
2936 "uniform sampler Texture_Color : register(s1),\n"
2937 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2938 "uniform sampler Texture_Gloss : register(s2),\n"
2941 "uniform sampler Texture_Glow : register(s3),\n"
2943 "#ifdef USEVERTEXTEXTUREBLEND\n"
2944 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2945 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2946 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2947 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2950 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2953 "#ifdef USECOLORMAPPING\n"
2954 "uniform sampler Texture_Pants : register(s4),\n"
2955 "uniform sampler Texture_Shirt : register(s7),\n"
2958 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2959 "uniform sampler Texture_FogMask : register(s8),\n"
2961 "#ifdef USELIGHTMAP\n"
2962 "uniform sampler Texture_Lightmap : register(s9),\n"
2964 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2965 "uniform sampler Texture_Deluxemap : register(s10),\n"
2967 "#ifdef USEREFLECTION\n"
2968 "uniform sampler Texture_Reflection : register(s7),\n"
2971 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2972 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2973 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2975 "#ifdef USEDEFERREDLIGHTMAP\n"
2976 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2977 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2978 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2979 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2982 "#ifdef USECOLORMAPPING\n"
2983 "uniform half3 Color_Pants : register(c7),\n"
2984 "uniform half3 Color_Shirt : register(c8),\n"
2987 "uniform float3 FogColor : register(c16),\n"
2988 "uniform float FogRangeRecip : register(c20),\n"
2989 "uniform float FogPlaneViewDist : register(c19),\n"
2990 "uniform float FogHeightFade : register(c17),\n"
2993 "#ifdef USEOFFSETMAPPING\n"
2994 "uniform float OffsetMapping_Scale : register(c24),\n"
2997 "#ifdef USEDEFERREDLIGHTMAP\n"
2998 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2999 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3000 "uniform half3 DeferredMod_Specular : register(c13),\n"
3002 "uniform half3 Color_Ambient : register(c3),\n"
3003 "uniform half3 Color_Diffuse : register(c4),\n"
3004 "uniform half3 Color_Specular : register(c5),\n"
3005 "uniform half SpecularPower : register(c36),\n"
3007 "uniform half3 Color_Glow : register(c6),\n"
3009 "uniform half Alpha : register(c0),\n"
3010 "#ifdef USEREFLECTION\n"
3011 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3012 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3013 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3014 "uniform half4 ReflectColor : register(c26),\n"
3016 "#ifdef USEREFLECTCUBE\n"
3017 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3018 "uniform sampler Texture_ReflectMask : register(s5),\n"
3019 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3021 "#ifdef MODE_LIGHTDIRECTION\n"
3022 "uniform half3 LightColor : register(c21),\n"
3024 "#ifdef MODE_LIGHTSOURCE\n"
3025 "uniform half3 LightColor : register(c21),\n"
3028 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3029 "uniform sampler Texture_Attenuation : register(s9),\n"
3030 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3033 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3035 "#ifdef USESHADOWMAP2D\n"
3036 "# ifdef USESHADOWSAMPLER\n"
3037 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3039 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3043 "#ifdef USESHADOWMAPVSDCT\n"
3044 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3047 "#if defined(USESHADOWMAP2D)\n"
3048 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3049 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3051 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3053 "out float4 gl_FragColor : COLOR\n"
3056 " float2 TexCoord = TexCoordBoth.xy;\n"
3057 "#ifdef USEVERTEXTEXTUREBLEND\n"
3058 " float2 TexCoord2 = TexCoordBoth.zw;\n"
3060 "#ifdef USEOFFSETMAPPING\n"
3061 " // apply offsetmapping\n"
3062 " float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3063 "#define TexCoord TexCoordOffset\n"
3066 " // combine the diffuse textures (base, pants, shirt)\n"
3067 " half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3068 "#ifdef USEALPHAKILL\n"
3069 " if (color.a < 0.5)\n"
3072 " color.a *= Alpha;\n"
3073 "#ifdef USECOLORMAPPING\n"
3074 " color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3076 "#ifdef USEVERTEXTEXTUREBLEND\n"
3077 " half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3078 " //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3079 " //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3080 " color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3082 " //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3085 " // get the surface normal\n"
3086 "#ifdef USEVERTEXTEXTUREBLEND\n"
3087 " half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3089 " half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3092 " // get the material colors\n"
3093 " half3 diffusetex = color.rgb;\n"
3094 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3095 "# ifdef USEVERTEXTEXTUREBLEND\n"
3096 " half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3098 " half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3102 "#ifdef USEREFLECTCUBE\n"
3103 " float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3104 " float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3105 " float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3106 " diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3112 "#ifdef MODE_LIGHTSOURCE\n"
3113 " // light source\n"
3114 "#ifdef USEDIFFUSE\n"
3115 " half3 lightnormal = half3(normalize(LightVector));\n"
3116 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3117 " color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3118 "#ifdef USESPECULAR\n"
3119 "#ifdef USEEXACTSPECULARMATH\n"
3120 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3122 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3123 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3125 " color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3128 " color.rgb = diffusetex * Color_Ambient;\n"
3130 " color.rgb *= LightColor;\n"
3131 " color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3132 "#if defined(USESHADOWMAP2D)\n"
3133 " color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3134 "#ifdef USESHADOWMAPVSDCT\n"
3135 ", Texture_CubeProjection\n"
3140 "# ifdef USECUBEFILTER\n"
3141 " color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3144 "#ifdef USESHADOWMAP2D\n"
3145 "#ifdef USESHADOWMAPVSDCT\n"
3146 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3148 "// float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3150 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3151 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3152 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3153 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3154 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3155 "// color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3156 "// color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3157 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3158 "// color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3159 "// color.r = half(shadowmaptc.z);\n"
3160 "// color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3161 "// color.r = half(shadowmaptc.z);\n"
3163 "// color.rgb = abs(CubeVector);\n"
3165 "// color.rgb = half3(1,1,1);\n"
3166 "#endif // MODE_LIGHTSOURCE\n"
3171 "#ifdef MODE_LIGHTDIRECTION\n"
3173 "#ifdef USEDIFFUSE\n"
3174 " half3 lightnormal = half3(normalize(LightVector));\n"
3176 "#define lightcolor LightColor\n"
3177 "#endif // MODE_LIGHTDIRECTION\n"
3178 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3180 " // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3181 " half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3182 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3183 " // convert modelspace light vector to tangentspace\n"
3184 " half3 lightnormal;\n"
3185 " lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3186 " lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3187 " lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3188 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3189 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3190 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3191 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3192 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3193 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3194 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3195 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3196 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3197 " lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3198 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3199 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3201 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3202 " half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3203 " half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3209 "#ifdef MODE_FAKELIGHT\n"
3211 "half3 lightnormal = half3(normalize(EyeVector));\n"
3212 "half3 lightcolor = half3(1.0);\n"
3213 "#endif // MODE_FAKELIGHT\n"
3218 "#ifdef MODE_LIGHTMAP\n"
3219 " color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3220 "#endif // MODE_LIGHTMAP\n"
3221 "#ifdef MODE_VERTEXCOLOR\n"
3222 " color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3223 "#endif // MODE_VERTEXCOLOR\n"
3224 "#ifdef MODE_FLATCOLOR\n"
3225 " color.rgb = diffusetex * Color_Ambient;\n"
3226 "#endif // MODE_FLATCOLOR\n"
3232 "# ifdef USEDIFFUSE\n"
3233 " half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3234 "# ifdef USESPECULAR\n"
3235 "# ifdef USEEXACTSPECULARMATH\n"
3236 " half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3238 " half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3239 " half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3241 " color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3243 " color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3246 " color.rgb = diffusetex * Color_Ambient;\n"
3250 "#ifdef USESHADOWMAPORTHO\n"
3251 " color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3254 "#ifdef USEDEFERREDLIGHTMAP\n"
3255 " float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3256 " color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3257 " color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3258 "// color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3259 "// color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3263 "#ifdef USEVERTEXTEXTUREBLEND\n"
3264 " color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3266 " color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3271 " color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3274 " // 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"
3275 "#ifdef USEREFLECTION\n"
3276 " float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3277 " //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3278 " float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3279 " float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3280 " // FIXME temporary hack to detect the case that the reflection\n"
3281 " // gets blackened at edges due to leaving the area that contains actual\n"
3283 " // Remove this 'ack once we have a better way to stop this thing from\n"
3285 " float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3286 " 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 " ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3290 " color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3293 " gl_FragColor = float4(color);\n"
3295 "#endif // FRAGMENT_SHADER\n"
3297 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3298 "#endif // !MODE_DEFERREDGEOMETRY\n"
3299 "#endif // !MODE_WATER\n"
3300 "#endif // !MODE_REFRACTION\n"
3301 "#endif // !MODE_BLOOMBLUR\n"
3302 "#endif // !MODE_GENERIC\n"
3303 "#endif // !MODE_POSTPROCESS\n"
3304 "#endif // !MODE_SHOWDEPTH\n"
3305 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3308 char *glslshaderstring = NULL;
3309 char *cgshaderstring = NULL;
3310 char *hlslshaderstring = NULL;
3312 //=======================================================================================================================================================
3314 typedef struct shaderpermutationinfo_s
3316 const char *pretext;
3319 shaderpermutationinfo_t;
3321 typedef struct shadermodeinfo_s
3323 const char *vertexfilename;
3324 const char *geometryfilename;
3325 const char *fragmentfilename;
3326 const char *pretext;
3331 typedef enum shaderpermutation_e
3333 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3334 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3335 SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3336 SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3337 SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3338 SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3339 SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3340 SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3341 SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3342 SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3343 SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3344 SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3345 SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3346 SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3347 SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3348 SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3349 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3350 SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3351 SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3352 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3353 SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3354 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3355 SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3356 SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3357 SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3358 SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3359 SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3360 SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3361 SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3363 shaderpermutation_t;
3365 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3366 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3368 {"#define USEDIFFUSE\n", " diffuse"},
3369 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3370 {"#define USEVIEWTINT\n", " viewtint"},
3371 {"#define USECOLORMAPPING\n", " colormapping"},
3372 {"#define USESATURATION\n", " saturation"},
3373 {"#define USEFOGINSIDE\n", " foginside"},
3374 {"#define USEFOGOUTSIDE\n", " fogoutside"},
3375 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3376 {"#define USEGAMMARAMPS\n", " gammaramps"},
3377 {"#define USECUBEFILTER\n", " cubefilter"},
3378 {"#define USEGLOW\n", " glow"},
3379 {"#define USEBLOOM\n", " bloom"},
3380 {"#define USESPECULAR\n", " specular"},
3381 {"#define USEPOSTPROCESSING\n", " postprocessing"},
3382 {"#define USEREFLECTION\n", " reflection"},
3383 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3384 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3385 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3386 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3387 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3388 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3389 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3390 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3391 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3392 {"#define USEALPHAKILL\n", " alphakill"},
3393 {"#define USEREFLECTCUBE\n", " reflectcube"},
3394 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3397 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3398 typedef enum shadermode_e
3400 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3401 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3402 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3403 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3404 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3405 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3406 SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3407 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3408 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3409 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3410 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3411 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3412 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3413 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3414 SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3415 SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3420 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3421 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3423 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3424 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3425 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3426 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3427 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3428 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3429 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3430 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3431 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3432 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3433 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3434 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3435 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3436 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3437 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3438 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3442 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3444 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3445 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3446 {"cg/default.cg", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3447 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3448 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3449 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3450 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3451 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3452 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3453 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3454 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3455 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3456 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3457 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3458 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3459 {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3464 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3466 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3467 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3468 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3469 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3470 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3471 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3472 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3473 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3474 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3475 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3476 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3477 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3478 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3479 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3480 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3484 struct r_glsl_permutation_s;
3485 typedef struct r_glsl_permutation_s
3487 /// hash lookup data
3488 struct r_glsl_permutation_s *hashnext;
3490 unsigned int permutation;
3492 /// indicates if we have tried compiling this permutation already
3494 /// 0 if compilation failed
3496 /// locations of detected uniforms in program object, or -1 if not found
3497 int loc_Texture_First;
3498 int loc_Texture_Second;
3499 int loc_Texture_GammaRamps;
3500 int loc_Texture_Normal;
3501 int loc_Texture_Color;
3502 int loc_Texture_Gloss;
3503 int loc_Texture_Glow;
3504 int loc_Texture_SecondaryNormal;
3505 int loc_Texture_SecondaryColor;
3506 int loc_Texture_SecondaryGloss;
3507 int loc_Texture_SecondaryGlow;
3508 int loc_Texture_Pants;
3509 int loc_Texture_Shirt;
3510 int loc_Texture_FogHeightTexture;
3511 int loc_Texture_FogMask;
3512 int loc_Texture_Lightmap;
3513 int loc_Texture_Deluxemap;
3514 int loc_Texture_Attenuation;
3515 int loc_Texture_Cube;
3516 int loc_Texture_Refraction;
3517 int loc_Texture_Reflection;
3518 int loc_Texture_ShadowMap2D;
3519 int loc_Texture_CubeProjection;
3520 int loc_Texture_ScreenDepth;
3521 int loc_Texture_ScreenNormalMap;
3522 int loc_Texture_ScreenDiffuse;
3523 int loc_Texture_ScreenSpecular;
3524 int loc_Texture_ReflectMask;
3525 int loc_Texture_ReflectCube;
3527 int loc_BloomBlur_Parameters;
3529 int loc_Color_Ambient;
3530 int loc_Color_Diffuse;
3531 int loc_Color_Specular;
3533 int loc_Color_Pants;
3534 int loc_Color_Shirt;
3535 int loc_DeferredColor_Ambient;
3536 int loc_DeferredColor_Diffuse;
3537 int loc_DeferredColor_Specular;
3538 int loc_DeferredMod_Diffuse;
3539 int loc_DeferredMod_Specular;
3540 int loc_DistortScaleRefractReflect;
3541 int loc_EyePosition;
3543 int loc_FogHeightFade;
3545 int loc_FogPlaneViewDist;
3546 int loc_FogRangeRecip;
3549 int loc_LightPosition;
3550 int loc_OffsetMapping_Scale;
3552 int loc_ReflectColor;
3553 int loc_ReflectFactor;
3554 int loc_ReflectOffset;
3555 int loc_RefractColor;
3557 int loc_ScreenCenterRefractReflect;
3558 int loc_ScreenScaleRefractReflect;
3559 int loc_ScreenToDepth;
3560 int loc_ShadowMap_Parameters;
3561 int loc_ShadowMap_TextureScale;
3562 int loc_SpecularPower;
3567 int loc_ViewTintColor;
3568 int loc_ViewToLight;
3569 int loc_ModelToLight;
3571 int loc_BackgroundTexMatrix;
3572 int loc_ModelViewProjectionMatrix;
3573 int loc_ModelViewMatrix;
3574 int loc_PixelToScreenTexCoord;
3575 int loc_ModelToReflectCube;
3576 int loc_ShadowMapMatrix;
3577 int loc_BloomColorSubtract;
3578 int loc_NormalmapScrollBlend;
3580 r_glsl_permutation_t;
3582 #define SHADERPERMUTATION_HASHSIZE 256
3585 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3586 // these can NOT degrade! only use for simple stuff
3589 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3590 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3592 #define SHADERSTATICPARMS_COUNT 2
3594 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3595 static int shaderstaticparms_count = 0;
3597 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3598 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3599 qboolean R_CompileShader_CheckStaticParms(void)
3601 static int r_compileshader_staticparms_save[1];
3602 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3603 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3606 if (r_glsl_saturation_redcompensate.integer)
3607 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3608 if(r_shadow_glossexact.integer)
3609 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3611 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
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");
3625 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3629 /// information about each possible shader permutation
3630 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3631 /// currently selected permutation
3632 r_glsl_permutation_t *r_glsl_permutation;
3633 /// storage for permutations linked in the hash table
3634 memexpandablearray_t r_glsl_permutationarray;
3636 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3638 //unsigned int hashdepth = 0;
3639 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3640 r_glsl_permutation_t *p;
3641 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3643 if (p->mode == mode && p->permutation == permutation)
3645 //if (hashdepth > 10)
3646 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3651 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3653 p->permutation = permutation;
3654 p->hashnext = r_glsl_permutationhash[mode][hashindex];
3655 r_glsl_permutationhash[mode][hashindex] = p;
3656 //if (hashdepth > 10)
3657 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3661 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3664 if (!filename || !filename[0])
3666 if (!strcmp(filename, "glsl/default.glsl"))
3668 if (!glslshaderstring)
3670 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3671 if (glslshaderstring)
3672 Con_DPrintf("Loading shaders from file %s...\n", filename);
3674 glslshaderstring = (char *)builtinshaderstring;
3676 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3677 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3678 return shaderstring;
3680 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3683 if (printfromdisknotice)
3684 Con_DPrintf("from disk %s... ", filename);
3685 return shaderstring;
3687 return shaderstring;
3690 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3693 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3694 char *vertexstring, *geometrystring, *fragmentstring;
3695 char permutationname[256];
3696 int vertstrings_count = 0;
3697 int geomstrings_count = 0;
3698 int fragstrings_count = 0;
3699 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3700 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3701 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3708 permutationname[0] = 0;
3709 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
3710 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3711 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3713 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3715 // the first pretext is which type of shader to compile as
3716 // (later these will all be bound together as a program object)
3717 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3718 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3719 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3721 // the second pretext is the mode (for example a light source)
3722 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3723 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3724 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3725 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3727 // now add all the permutation pretexts
3728 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3730 if (permutation & (1<<i))
3732 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3733 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3734 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3735 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3739 // keep line numbers correct
3740 vertstrings_list[vertstrings_count++] = "\n";
3741 geomstrings_list[geomstrings_count++] = "\n";
3742 fragstrings_list[fragstrings_count++] = "\n";
3747 R_CompileShader_AddStaticParms(mode, permutation);
3748 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3749 vertstrings_count += shaderstaticparms_count;
3750 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3751 geomstrings_count += shaderstaticparms_count;
3752 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3753 fragstrings_count += shaderstaticparms_count;
3755 // now append the shader text itself
3756 vertstrings_list[vertstrings_count++] = vertexstring;
3757 geomstrings_list[geomstrings_count++] = geometrystring;
3758 fragstrings_list[fragstrings_count++] = fragmentstring;
3760 // if any sources were NULL, clear the respective list
3762 vertstrings_count = 0;
3763 if (!geometrystring)
3764 geomstrings_count = 0;
3765 if (!fragmentstring)
3766 fragstrings_count = 0;
3768 // compile the shader program
3769 if (vertstrings_count + geomstrings_count + fragstrings_count)
3770 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3774 qglUseProgramObjectARB(p->program);CHECKGLERROR
3775 // look up all the uniform variable names we care about, so we don't
3776 // have to look them up every time we set them
3778 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
3779 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
3780 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3781 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
3782 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
3783 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3784 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
3785 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3786 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3787 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3788 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3789 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
3790 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3791 p->loc_Texture_FogHeightTexture = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3792 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3793 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3794 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3795 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3796 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
3797 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3798 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3799 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3800 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3801 p->loc_Texture_ScreenDepth = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3802 p->loc_Texture_ScreenNormalMap = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3803 p->loc_Texture_ScreenDiffuse = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3804 p->loc_Texture_ScreenSpecular = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3805 p->loc_Texture_ReflectMask = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3806 p->loc_Texture_ReflectCube = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3807 p->loc_Alpha = qglGetUniformLocationARB(p->program, "Alpha");
3808 p->loc_BloomBlur_Parameters = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3809 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
3810 p->loc_Color_Ambient = qglGetUniformLocationARB(p->program, "Color_Ambient");
3811 p->loc_Color_Diffuse = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3812 p->loc_Color_Specular = qglGetUniformLocationARB(p->program, "Color_Specular");
3813 p->loc_Color_Glow = qglGetUniformLocationARB(p->program, "Color_Glow");
3814 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
3815 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
3816 p->loc_DeferredColor_Ambient = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3817 p->loc_DeferredColor_Diffuse = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3818 p->loc_DeferredColor_Specular = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3819 p->loc_DeferredMod_Diffuse = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3820 p->loc_DeferredMod_Specular = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3821 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3822 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
3823 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
3824 p->loc_FogHeightFade = qglGetUniformLocationARB(p->program, "FogHeightFade");
3825 p->loc_FogPlane = qglGetUniformLocationARB(p->program, "FogPlane");
3826 p->loc_FogPlaneViewDist = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3827 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3828 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
3829 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
3830 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
3831 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3832 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
3833 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
3834 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
3835 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
3836 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
3837 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
3838 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3839 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3840 p->loc_ScreenToDepth = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3841 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3842 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3843 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
3844 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
3845 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
3846 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
3847 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
3848 p->loc_ViewTintColor = qglGetUniformLocationARB(p->program, "ViewTintColor");
3849 p->loc_ViewToLight = qglGetUniformLocationARB(p->program, "ViewToLight");
3850 p->loc_ModelToLight = qglGetUniformLocationARB(p->program, "ModelToLight");
3851 p->loc_TexMatrix = qglGetUniformLocationARB(p->program, "TexMatrix");
3852 p->loc_BackgroundTexMatrix = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3853 p->loc_ModelViewMatrix = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3854 p->loc_ModelViewProjectionMatrix = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3855 p->loc_PixelToScreenTexCoord = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3856 p->loc_ModelToReflectCube = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3857 p->loc_ShadowMapMatrix = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3858 p->loc_BloomColorSubtract = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3859 p->loc_NormalmapScrollBlend = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3860 // initialize the samplers to refer to the texture units we use
3861 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
3862 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
3863 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
3864 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
3865 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
3866 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
3867 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
3868 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3869 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3870 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3871 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
3872 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
3873 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
3874 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3875 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
3876 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
3877 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
3878 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
3879 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
3880 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
3881 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
3882 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
3883 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3884 if (p->loc_Texture_ScreenDepth >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth , GL20TU_SCREENDEPTH);
3885 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3886 if (p->loc_Texture_ScreenDiffuse >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse , GL20TU_SCREENDIFFUSE);
3887 if (p->loc_Texture_ScreenSpecular >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3888 if (p->loc_Texture_ReflectMask >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask , GL20TU_REFLECTMASK);
3889 if (p->loc_Texture_ReflectCube >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube , GL20TU_REFLECTCUBE);
3891 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3894 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
3898 Mem_Free(vertexstring);
3900 Mem_Free(geometrystring);
3902 Mem_Free(fragmentstring);
3905 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3907 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3908 if (r_glsl_permutation != perm)
3910 r_glsl_permutation = perm;
3911 if (!r_glsl_permutation->program)
3913 if (!r_glsl_permutation->compiled)
3914 R_GLSL_CompilePermutation(perm, mode, permutation);
3915 if (!r_glsl_permutation->program)
3917 // remove features until we find a valid permutation
3919 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3921 // reduce i more quickly whenever it would not remove any bits
3922 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3923 if (!(permutation & j))
3926 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3927 if (!r_glsl_permutation->compiled)
3928 R_GLSL_CompilePermutation(perm, mode, permutation);
3929 if (r_glsl_permutation->program)
3932 if (i >= SHADERPERMUTATION_COUNT)
3934 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3935 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3936 qglUseProgramObjectARB(0);CHECKGLERROR
3937 return; // no bit left to clear, entire mode is broken
3942 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3944 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3945 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3946 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3950 #include <Cg/cgGL.h>
3951 struct r_cg_permutation_s;
3952 typedef struct r_cg_permutation_s
3954 /// hash lookup data
3955 struct r_cg_permutation_s *hashnext;
3957 unsigned int permutation;
3959 /// indicates if we have tried compiling this permutation already
3961 /// 0 if compilation failed
3964 /// locations of detected parameters in programs, or NULL if not found
3965 CGparameter vp_EyePosition;
3966 CGparameter vp_FogPlane;
3967 CGparameter vp_LightDir;
3968 CGparameter vp_LightPosition;
3969 CGparameter vp_ModelToLight;
3970 CGparameter vp_TexMatrix;
3971 CGparameter vp_BackgroundTexMatrix;
3972 CGparameter vp_ModelViewProjectionMatrix;
3973 CGparameter vp_ModelViewMatrix;
3974 CGparameter vp_ShadowMapMatrix;
3976 CGparameter fp_Texture_First;
3977 CGparameter fp_Texture_Second;
3978 CGparameter fp_Texture_GammaRamps;
3979 CGparameter fp_Texture_Normal;
3980 CGparameter fp_Texture_Color;
3981 CGparameter fp_Texture_Gloss;
3982 CGparameter fp_Texture_Glow;
3983 CGparameter fp_Texture_SecondaryNormal;
3984 CGparameter fp_Texture_SecondaryColor;
3985 CGparameter fp_Texture_SecondaryGloss;
3986 CGparameter fp_Texture_SecondaryGlow;
3987 CGparameter fp_Texture_Pants;
3988 CGparameter fp_Texture_Shirt;
3989 CGparameter fp_Texture_FogHeightTexture;
3990 CGparameter fp_Texture_FogMask;
3991 CGparameter fp_Texture_Lightmap;
3992 CGparameter fp_Texture_Deluxemap;
3993 CGparameter fp_Texture_Attenuation;
3994 CGparameter fp_Texture_Cube;
3995 CGparameter fp_Texture_Refraction;
3996 CGparameter fp_Texture_Reflection;
3997 CGparameter fp_Texture_ShadowMap2D;
3998 CGparameter fp_Texture_CubeProjection;
3999 CGparameter fp_Texture_ScreenDepth;
4000 CGparameter fp_Texture_ScreenNormalMap;
4001 CGparameter fp_Texture_ScreenDiffuse;
4002 CGparameter fp_Texture_ScreenSpecular;
4003 CGparameter fp_Texture_ReflectMask;
4004 CGparameter fp_Texture_ReflectCube;
4005 CGparameter fp_Alpha;
4006 CGparameter fp_BloomBlur_Parameters;
4007 CGparameter fp_ClientTime;
4008 CGparameter fp_Color_Ambient;
4009 CGparameter fp_Color_Diffuse;
4010 CGparameter fp_Color_Specular;
4011 CGparameter fp_Color_Glow;
4012 CGparameter fp_Color_Pants;
4013 CGparameter fp_Color_Shirt;
4014 CGparameter fp_DeferredColor_Ambient;
4015 CGparameter fp_DeferredColor_Diffuse;
4016 CGparameter fp_DeferredColor_Specular;
4017 CGparameter fp_DeferredMod_Diffuse;
4018 CGparameter fp_DeferredMod_Specular;
4019 CGparameter fp_DistortScaleRefractReflect;
4020 CGparameter fp_EyePosition;
4021 CGparameter fp_FogColor;
4022 CGparameter fp_FogHeightFade;
4023 CGparameter fp_FogPlane;
4024 CGparameter fp_FogPlaneViewDist;
4025 CGparameter fp_FogRangeRecip;
4026 CGparameter fp_LightColor;
4027 CGparameter fp_LightDir;
4028 CGparameter fp_LightPosition;
4029 CGparameter fp_OffsetMapping_Scale;
4030 CGparameter fp_PixelSize;
4031 CGparameter fp_ReflectColor;
4032 CGparameter fp_ReflectFactor;
4033 CGparameter fp_ReflectOffset;
4034 CGparameter fp_RefractColor;
4035 CGparameter fp_Saturation;
4036 CGparameter fp_ScreenCenterRefractReflect;
4037 CGparameter fp_ScreenScaleRefractReflect;
4038 CGparameter fp_ScreenToDepth;
4039 CGparameter fp_ShadowMap_Parameters;
4040 CGparameter fp_ShadowMap_TextureScale;
4041 CGparameter fp_SpecularPower;
4042 CGparameter fp_UserVec1;
4043 CGparameter fp_UserVec2;
4044 CGparameter fp_UserVec3;
4045 CGparameter fp_UserVec4;
4046 CGparameter fp_ViewTintColor;
4047 CGparameter fp_ViewToLight;
4048 CGparameter fp_PixelToScreenTexCoord;
4049 CGparameter fp_ModelToReflectCube;
4050 CGparameter fp_BloomColorSubtract;
4051 CGparameter fp_NormalmapScrollBlend;
4055 /// information about each possible shader permutation
4056 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4057 /// currently selected permutation
4058 r_cg_permutation_t *r_cg_permutation;
4059 /// storage for permutations linked in the hash table
4060 memexpandablearray_t r_cg_permutationarray;
4062 #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));}}
4064 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4066 //unsigned int hashdepth = 0;
4067 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4068 r_cg_permutation_t *p;
4069 for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4071 if (p->mode == mode && p->permutation == permutation)
4073 //if (hashdepth > 10)
4074 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4079 p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4081 p->permutation = permutation;
4082 p->hashnext = r_cg_permutationhash[mode][hashindex];
4083 r_cg_permutationhash[mode][hashindex] = p;
4084 //if (hashdepth > 10)
4085 // Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4089 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4092 if (!filename || !filename[0])
4094 if (!strcmp(filename, "cg/default.cg"))
4096 if (!cgshaderstring)
4098 cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4100 Con_DPrintf("Loading shaders from file %s...\n", filename);
4102 cgshaderstring = (char *)builtincgshaderstring;
4104 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4105 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4106 return shaderstring;
4108 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4111 if (printfromdisknotice)
4112 Con_DPrintf("from disk %s... ", filename);
4113 return shaderstring;
4115 return shaderstring;
4118 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4120 // TODO: load or create .fp and .vp shader files
4123 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4126 shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4127 int vertstring_length = 0;
4128 int geomstring_length = 0;
4129 int fragstring_length = 0;
4131 char *vertexstring, *geometrystring, *fragmentstring;
4132 char *vertstring, *geomstring, *fragstring;
4133 char permutationname[256];
4134 char cachename[256];
4135 CGprofile vertexProfile;
4136 CGprofile fragmentProfile;
4137 int vertstrings_count = 0;
4138 int geomstrings_count = 0;
4139 int fragstrings_count = 0;
4140 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4141 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4142 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4150 permutationname[0] = 0;
4152 vertexstring = R_CG_GetText(modeinfo->vertexfilename, true);
4153 geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4154 fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4156 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4157 strlcat(cachename, "cg/", sizeof(cachename));
4159 // the first pretext is which type of shader to compile as
4160 // (later these will all be bound together as a program object)
4161 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4162 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4163 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4165 // the second pretext is the mode (for example a light source)
4166 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4167 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4168 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4169 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4170 strlcat(cachename, modeinfo->name, sizeof(cachename));
4172 // now add all the permutation pretexts
4173 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4175 if (permutation & (1<<i))
4177 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4178 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4179 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4180 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4181 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4185 // keep line numbers correct
4186 vertstrings_list[vertstrings_count++] = "\n";
4187 geomstrings_list[geomstrings_count++] = "\n";
4188 fragstrings_list[fragstrings_count++] = "\n";
4193 R_CompileShader_AddStaticParms(mode, permutation);
4194 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4195 vertstrings_count += shaderstaticparms_count;
4196 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4197 geomstrings_count += shaderstaticparms_count;
4198 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4199 fragstrings_count += shaderstaticparms_count;
4201 // replace spaces in the cachename with _ characters
4202 for (i = 0;cachename[i];i++)
4203 if (cachename[i] == ' ')
4206 // now append the shader text itself
4207 vertstrings_list[vertstrings_count++] = vertexstring;
4208 geomstrings_list[geomstrings_count++] = geometrystring;
4209 fragstrings_list[fragstrings_count++] = fragmentstring;
4211 // if any sources were NULL, clear the respective list
4213 vertstrings_count = 0;
4214 if (!geometrystring)
4215 geomstrings_count = 0;
4216 if (!fragmentstring)
4217 fragstrings_count = 0;
4219 vertstring_length = 0;
4220 for (i = 0;i < vertstrings_count;i++)
4221 vertstring_length += strlen(vertstrings_list[i]);
4222 vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4223 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4224 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4226 geomstring_length = 0;
4227 for (i = 0;i < geomstrings_count;i++)
4228 geomstring_length += strlen(geomstrings_list[i]);
4229 geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4230 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4231 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4233 fragstring_length = 0;
4234 for (i = 0;i < fragstrings_count;i++)
4235 fragstring_length += strlen(fragstrings_list[i]);
4236 fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4237 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4238 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4242 //vertexProfile = CG_PROFILE_ARBVP1;
4243 //fragmentProfile = CG_PROFILE_ARBFP1;
4244 vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4245 fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4246 //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4247 //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4248 //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4251 // try to load the cached shader, or generate one
4252 R_CG_CacheShader(p, cachename, vertstring, fragstring);
4254 // if caching failed, do a dynamic compile for now
4256 if (vertstring[0] && !p->vprogram)
4257 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4259 if (fragstring[0] && !p->fprogram)
4260 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4263 // look up all the uniform variable names we care about, so we don't
4264 // have to look them up every time we set them
4268 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4269 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4270 p->vp_EyePosition = cgGetNamedParameter(p->vprogram, "EyePosition");
4271 p->vp_FogPlane = cgGetNamedParameter(p->vprogram, "FogPlane");
4272 p->vp_LightDir = cgGetNamedParameter(p->vprogram, "LightDir");
4273 p->vp_LightPosition = cgGetNamedParameter(p->vprogram, "LightPosition");
4274 p->vp_ModelToLight = cgGetNamedParameter(p->vprogram, "ModelToLight");
4275 p->vp_TexMatrix = cgGetNamedParameter(p->vprogram, "TexMatrix");
4276 p->vp_BackgroundTexMatrix = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4277 p->vp_ModelViewProjectionMatrix = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4278 p->vp_ModelViewMatrix = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4279 p->vp_ShadowMapMatrix = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4285 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4286 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4287 p->fp_Texture_First = cgGetNamedParameter(p->fprogram, "Texture_First");
4288 p->fp_Texture_Second = cgGetNamedParameter(p->fprogram, "Texture_Second");
4289 p->fp_Texture_GammaRamps = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4290 p->fp_Texture_Normal = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4291 p->fp_Texture_Color = cgGetNamedParameter(p->fprogram, "Texture_Color");
4292 p->fp_Texture_Gloss = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4293 p->fp_Texture_Glow = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4294 p->fp_Texture_SecondaryNormal = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4295 p->fp_Texture_SecondaryColor = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4296 p->fp_Texture_SecondaryGloss = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4297 p->fp_Texture_SecondaryGlow = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4298 p->fp_Texture_Pants = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4299 p->fp_Texture_Shirt = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4300 p->fp_Texture_FogHeightTexture = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4301 p->fp_Texture_FogMask = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4302 p->fp_Texture_Lightmap = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4303 p->fp_Texture_Deluxemap = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4304 p->fp_Texture_Attenuation = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4305 p->fp_Texture_Cube = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4306 p->fp_Texture_Refraction = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4307 p->fp_Texture_Reflection = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4308 p->fp_Texture_ShadowMap2D = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4309 p->fp_Texture_CubeProjection = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4310 p->fp_Texture_ScreenDepth = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4311 p->fp_Texture_ScreenNormalMap = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4312 p->fp_Texture_ScreenDiffuse = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4313 p->fp_Texture_ScreenSpecular = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4314 p->fp_Texture_ReflectMask = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4315 p->fp_Texture_ReflectCube = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4316 p->fp_Alpha = cgGetNamedParameter(p->fprogram, "Alpha");
4317 p->fp_BloomBlur_Parameters = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4318 p->fp_ClientTime = cgGetNamedParameter(p->fprogram, "ClientTime");
4319 p->fp_Color_Ambient = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4320 p->fp_Color_Diffuse = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4321 p->fp_Color_Specular = cgGetNamedParameter(p->fprogram, "Color_Specular");
4322 p->fp_Color_Glow = cgGetNamedParameter(p->fprogram, "Color_Glow");
4323 p->fp_Color_Pants = cgGetNamedParameter(p->fprogram, "Color_Pants");
4324 p->fp_Color_Shirt = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4325 p->fp_DeferredColor_Ambient = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4326 p->fp_DeferredColor_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4327 p->fp_DeferredColor_Specular = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4328 p->fp_DeferredMod_Diffuse = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4329 p->fp_DeferredMod_Specular = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4330 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4331 p->fp_EyePosition = cgGetNamedParameter(p->fprogram, "EyePosition");
4332 p->fp_FogColor = cgGetNamedParameter(p->fprogram, "FogColor");
4333 p->fp_FogHeightFade = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4334 p->fp_FogPlane = cgGetNamedParameter(p->fprogram, "FogPlane");
4335 p->fp_FogPlaneViewDist = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4336 p->fp_FogRangeRecip = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4337 p->fp_LightColor = cgGetNamedParameter(p->fprogram, "LightColor");
4338 p->fp_LightDir = cgGetNamedParameter(p->fprogram, "LightDir");
4339 p->fp_LightPosition = cgGetNamedParameter(p->fprogram, "LightPosition");
4340 p->fp_OffsetMapping_Scale = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4341 p->fp_PixelSize = cgGetNamedParameter(p->fprogram, "PixelSize");
4342 p->fp_ReflectColor = cgGetNamedParameter(p->fprogram, "ReflectColor");
4343 p->fp_ReflectFactor = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4344 p->fp_ReflectOffset = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4345 p->fp_RefractColor = cgGetNamedParameter(p->fprogram, "RefractColor");
4346 p->fp_Saturation = cgGetNamedParameter(p->fprogram, "Saturation");
4347 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4348 p->fp_ScreenScaleRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4349 p->fp_ScreenToDepth = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4350 p->fp_ShadowMap_Parameters = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4351 p->fp_ShadowMap_TextureScale = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4352 p->fp_SpecularPower = cgGetNamedParameter(p->fprogram, "SpecularPower");
4353 p->fp_UserVec1 = cgGetNamedParameter(p->fprogram, "UserVec1");
4354 p->fp_UserVec2 = cgGetNamedParameter(p->fprogram, "UserVec2");
4355 p->fp_UserVec3 = cgGetNamedParameter(p->fprogram, "UserVec3");
4356 p->fp_UserVec4 = cgGetNamedParameter(p->fprogram, "UserVec4");
4357 p->fp_ViewTintColor = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4358 p->fp_ViewToLight = cgGetNamedParameter(p->fprogram, "ViewToLight");
4359 p->fp_PixelToScreenTexCoord = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4360 p->fp_ModelToReflectCube = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4361 p->fp_BloomColorSubtract = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4362 p->fp_NormalmapScrollBlend = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4366 if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4367 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4369 Con_Printf("^1CG shader %s failed! some features may not work properly.\n", permutationname);
4373 Mem_Free(vertstring);
4375 Mem_Free(geomstring);
4377 Mem_Free(fragstring);
4379 Mem_Free(vertexstring);
4381 Mem_Free(geometrystring);
4383 Mem_Free(fragmentstring);
4386 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4388 r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4391 if (r_cg_permutation != perm)
4393 r_cg_permutation = perm;
4394 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4396 if (!r_cg_permutation->compiled)
4397 R_CG_CompilePermutation(perm, mode, permutation);
4398 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4400 // remove features until we find a valid permutation
4402 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4404 // reduce i more quickly whenever it would not remove any bits
4405 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4406 if (!(permutation & j))
4409 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4410 if (!r_cg_permutation->compiled)
4411 R_CG_CompilePermutation(perm, mode, permutation);
4412 if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4415 if (i >= SHADERPERMUTATION_COUNT)
4417 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4418 r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4419 return; // no bit left to clear, entire mode is broken
4425 if (r_cg_permutation->vprogram)
4427 cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4428 cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4429 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4433 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4434 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4436 if (r_cg_permutation->fprogram)
4438 cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4439 cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4440 cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4444 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4445 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4449 if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4450 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4451 if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4454 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4456 cgGLSetTextureParameter(param, R_GetTexture(tex));
4457 cgGLEnableTextureParameter(param);
4465 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4466 extern D3DCAPS9 vid_d3d9caps;
4469 struct r_hlsl_permutation_s;
4470 typedef struct r_hlsl_permutation_s
4472 /// hash lookup data
4473 struct r_hlsl_permutation_s *hashnext;
4475 unsigned int permutation;
4477 /// indicates if we have tried compiling this permutation already
4479 /// NULL if compilation failed
4480 IDirect3DVertexShader9 *vertexshader;
4481 IDirect3DPixelShader9 *pixelshader;
4483 r_hlsl_permutation_t;
4485 typedef enum D3DVSREGISTER_e
4487 D3DVSREGISTER_TexMatrix = 0, // float4x4
4488 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4489 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4490 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4491 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4492 D3DVSREGISTER_ModelToLight = 20, // float4x4
4493 D3DVSREGISTER_EyePosition = 24,
4494 D3DVSREGISTER_FogPlane = 25,
4495 D3DVSREGISTER_LightDir = 26,
4496 D3DVSREGISTER_LightPosition = 27,
4500 typedef enum D3DPSREGISTER_e
4502 D3DPSREGISTER_Alpha = 0,
4503 D3DPSREGISTER_BloomBlur_Parameters = 1,
4504 D3DPSREGISTER_ClientTime = 2,
4505 D3DPSREGISTER_Color_Ambient = 3,
4506 D3DPSREGISTER_Color_Diffuse = 4,
4507 D3DPSREGISTER_Color_Specular = 5,
4508 D3DPSREGISTER_Color_Glow = 6,
4509 D3DPSREGISTER_Color_Pants = 7,
4510 D3DPSREGISTER_Color_Shirt = 8,
4511 D3DPSREGISTER_DeferredColor_Ambient = 9,
4512 D3DPSREGISTER_DeferredColor_Diffuse = 10,
4513 D3DPSREGISTER_DeferredColor_Specular = 11,
4514 D3DPSREGISTER_DeferredMod_Diffuse = 12,
4515 D3DPSREGISTER_DeferredMod_Specular = 13,
4516 D3DPSREGISTER_DistortScaleRefractReflect = 14,
4517 D3DPSREGISTER_EyePosition = 15, // unused
4518 D3DPSREGISTER_FogColor = 16,
4519 D3DPSREGISTER_FogHeightFade = 17,
4520 D3DPSREGISTER_FogPlane = 18,
4521 D3DPSREGISTER_FogPlaneViewDist = 19,
4522 D3DPSREGISTER_FogRangeRecip = 20,
4523 D3DPSREGISTER_LightColor = 21,
4524 D3DPSREGISTER_LightDir = 22, // unused
4525 D3DPSREGISTER_LightPosition = 23,
4526 D3DPSREGISTER_OffsetMapping_Scale = 24,
4527 D3DPSREGISTER_PixelSize = 25,
4528 D3DPSREGISTER_ReflectColor = 26,
4529 D3DPSREGISTER_ReflectFactor = 27,
4530 D3DPSREGISTER_ReflectOffset = 28,
4531 D3DPSREGISTER_RefractColor = 29,
4532 D3DPSREGISTER_Saturation = 30,
4533 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4534 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4535 D3DPSREGISTER_ScreenToDepth = 33,
4536 D3DPSREGISTER_ShadowMap_Parameters = 34,
4537 D3DPSREGISTER_ShadowMap_TextureScale = 35,
4538 D3DPSREGISTER_SpecularPower = 36,
4539 D3DPSREGISTER_UserVec1 = 37,
4540 D3DPSREGISTER_UserVec2 = 38,
4541 D3DPSREGISTER_UserVec3 = 39,
4542 D3DPSREGISTER_UserVec4 = 40,
4543 D3DPSREGISTER_ViewTintColor = 41,
4544 D3DPSREGISTER_PixelToScreenTexCoord = 42,
4545 D3DPSREGISTER_BloomColorSubtract = 43,
4546 D3DPSREGISTER_ViewToLight = 44, // float4x4
4547 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4548 D3DPSREGISTER_NormalmapScrollBlend = 52,
4553 /// information about each possible shader permutation
4554 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4555 /// currently selected permutation
4556 r_hlsl_permutation_t *r_hlsl_permutation;
4557 /// storage for permutations linked in the hash table
4558 memexpandablearray_t r_hlsl_permutationarray;
4560 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4562 //unsigned int hashdepth = 0;
4563 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4564 r_hlsl_permutation_t *p;
4565 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4567 if (p->mode == mode && p->permutation == permutation)
4569 //if (hashdepth > 10)
4570 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4575 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4577 p->permutation = permutation;
4578 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4579 r_hlsl_permutationhash[mode][hashindex] = p;
4580 //if (hashdepth > 10)
4581 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4585 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4588 if (!filename || !filename[0])
4590 if (!strcmp(filename, "hlsl/default.hlsl"))
4592 if (!hlslshaderstring)
4594 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4595 if (hlslshaderstring)
4596 Con_DPrintf("Loading shaders from file %s...\n", filename);
4598 hlslshaderstring = (char *)builtincgshaderstring;
4600 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4601 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4602 return shaderstring;
4604 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4607 if (printfromdisknotice)
4608 Con_DPrintf("from disk %s... ", filename);
4609 return shaderstring;
4611 return shaderstring;
4615 //#include <d3dx9shader.h>
4616 //#include <d3dx9mesh.h>
4618 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4620 DWORD *vsbin = NULL;
4621 DWORD *psbin = NULL;
4622 fs_offset_t vsbinsize;
4623 fs_offset_t psbinsize;
4624 // IDirect3DVertexShader9 *vs = NULL;
4625 // IDirect3DPixelShader9 *ps = NULL;
4626 ID3DXBuffer *vslog = NULL;
4627 ID3DXBuffer *vsbuffer = NULL;
4628 ID3DXConstantTable *vsconstanttable = NULL;
4629 ID3DXBuffer *pslog = NULL;
4630 ID3DXBuffer *psbuffer = NULL;
4631 ID3DXConstantTable *psconstanttable = NULL;
4634 char temp[MAX_INPUTLINE];
4635 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4636 qboolean debugshader = gl_paranoid.integer != 0;
4637 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4638 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4641 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4642 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4644 if ((!vsbin && vertstring) || (!psbin && fragstring))
4646 const char* dllnames_d3dx9 [] =
4670 dllhandle_t d3dx9_dll = NULL;
4671 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4672 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4673 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4674 dllfunction_t d3dx9_dllfuncs[] =
4676 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
4677 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
4678 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
4681 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4683 DWORD shaderflags = 0;
4685 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4686 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4687 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4688 if (vertstring && vertstring[0])
4692 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4693 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4694 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4695 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4698 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4701 vsbinsize = vsbuffer->GetBufferSize();
4702 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4703 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4704 vsbuffer->Release();
4708 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4709 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4713 if (fragstring && fragstring[0])
4717 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4718 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4719 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4720 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4723 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4726 psbinsize = psbuffer->GetBufferSize();
4727 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4728 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4729 psbuffer->Release();
4733 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4734 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4738 Sys_UnloadLibrary(&d3dx9_dll);
4741 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4745 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4746 if (FAILED(vsresult))
4747 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4748 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4749 if (FAILED(psresult))
4750 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4752 // free the shader data
4753 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4754 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4757 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4760 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4761 int vertstring_length = 0;
4762 int geomstring_length = 0;
4763 int fragstring_length = 0;
4765 char *vertexstring, *geometrystring, *fragmentstring;
4766 char *vertstring, *geomstring, *fragstring;
4767 char permutationname[256];
4768 char cachename[256];
4769 int vertstrings_count = 0;
4770 int geomstrings_count = 0;
4771 int fragstrings_count = 0;
4772 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4773 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4774 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4779 p->vertexshader = NULL;
4780 p->pixelshader = NULL;
4782 permutationname[0] = 0;
4784 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
4785 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4786 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4788 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4789 strlcat(cachename, "hlsl/", sizeof(cachename));
4791 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4792 vertstrings_count = 0;
4793 geomstrings_count = 0;
4794 fragstrings_count = 0;
4795 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4796 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4797 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4799 // the first pretext is which type of shader to compile as
4800 // (later these will all be bound together as a program object)
4801 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4802 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4803 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4805 // the second pretext is the mode (for example a light source)
4806 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4807 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4808 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4809 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4810 strlcat(cachename, modeinfo->name, sizeof(cachename));
4812 // now add all the permutation pretexts
4813 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4815 if (permutation & (1<<i))
4817 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4818 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4819 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4820 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4821 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4825 // keep line numbers correct
4826 vertstrings_list[vertstrings_count++] = "\n";
4827 geomstrings_list[geomstrings_count++] = "\n";
4828 fragstrings_list[fragstrings_count++] = "\n";
4833 R_CompileShader_AddStaticParms(mode, permutation);
4834 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4835 vertstrings_count += shaderstaticparms_count;
4836 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4837 geomstrings_count += shaderstaticparms_count;
4838 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4839 fragstrings_count += shaderstaticparms_count;
4841 // replace spaces in the cachename with _ characters
4842 for (i = 0;cachename[i];i++)
4843 if (cachename[i] == ' ')
4846 // now append the shader text itself
4847 vertstrings_list[vertstrings_count++] = vertexstring;
4848 geomstrings_list[geomstrings_count++] = geometrystring;
4849 fragstrings_list[fragstrings_count++] = fragmentstring;
4851 // if any sources were NULL, clear the respective list
4853 vertstrings_count = 0;
4854 if (!geometrystring)
4855 geomstrings_count = 0;
4856 if (!fragmentstring)
4857 fragstrings_count = 0;
4859 vertstring_length = 0;
4860 for (i = 0;i < vertstrings_count;i++)
4861 vertstring_length += strlen(vertstrings_list[i]);
4862 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4863 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4864 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4866 geomstring_length = 0;
4867 for (i = 0;i < geomstrings_count;i++)
4868 geomstring_length += strlen(geomstrings_list[i]);
4869 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4870 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4871 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4873 fragstring_length = 0;
4874 for (i = 0;i < fragstrings_count;i++)
4875 fragstring_length += strlen(fragstrings_list[i]);
4876 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4877 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4878 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4880 // try to load the cached shader, or generate one
4881 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4883 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4884 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4886 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
4890 Mem_Free(vertstring);
4892 Mem_Free(geomstring);
4894 Mem_Free(fragstring);
4896 Mem_Free(vertexstring);
4898 Mem_Free(geometrystring);
4900 Mem_Free(fragmentstring);
4903 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4904 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4905 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);}
4906 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);}
4907 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);}
4908 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);}
4910 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4911 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4912 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);}
4913 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);}
4914 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);}
4915 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);}
4917 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4919 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4920 if (r_hlsl_permutation != perm)
4922 r_hlsl_permutation = perm;
4923 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4925 if (!r_hlsl_permutation->compiled)
4926 R_HLSL_CompilePermutation(perm, mode, permutation);
4927 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4929 // remove features until we find a valid permutation
4931 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4933 // reduce i more quickly whenever it would not remove any bits
4934 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4935 if (!(permutation & j))
4938 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4939 if (!r_hlsl_permutation->compiled)
4940 R_HLSL_CompilePermutation(perm, mode, permutation);
4941 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4944 if (i >= SHADERPERMUTATION_COUNT)
4946 //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4947 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4948 return; // no bit left to clear, entire mode is broken
4952 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4953 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4955 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4956 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4957 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4961 void R_GLSL_Restart_f(void)
4963 unsigned int i, limit;
4964 if (glslshaderstring && glslshaderstring != builtinshaderstring)
4965 Mem_Free(glslshaderstring);
4966 glslshaderstring = NULL;
4967 if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4968 Mem_Free(cgshaderstring);
4969 cgshaderstring = NULL;
4970 if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4971 Mem_Free(hlslshaderstring);
4972 hlslshaderstring = NULL;
4973 switch(vid.renderpath)
4975 case RENDERPATH_D3D9:
4978 r_hlsl_permutation_t *p;
4979 r_hlsl_permutation = NULL;
4980 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4981 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4982 // cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4983 // cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4984 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4985 for (i = 0;i < limit;i++)
4987 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4989 if (p->vertexshader)
4990 IDirect3DVertexShader9_Release(p->vertexshader);
4992 IDirect3DPixelShader9_Release(p->pixelshader);
4993 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4996 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5000 case RENDERPATH_D3D10:
5001 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5003 case RENDERPATH_D3D11:
5004 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5006 case RENDERPATH_GL20:
5008 r_glsl_permutation_t *p;
5009 r_glsl_permutation = NULL;
5010 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5011 for (i = 0;i < limit;i++)
5013 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5015 GL_Backend_FreeProgram(p->program);
5016 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5019 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5022 case RENDERPATH_CGGL:
5025 r_cg_permutation_t *p;
5026 r_cg_permutation = NULL;
5027 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5028 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5029 cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5030 cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5031 limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5032 for (i = 0;i < limit;i++)
5034 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5037 cgDestroyProgram(p->vprogram);
5039 cgDestroyProgram(p->fprogram);
5040 Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5043 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5047 case RENDERPATH_GL13:
5048 case RENDERPATH_GL11:
5053 void R_GLSL_DumpShader_f(void)
5058 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5061 FS_Print(file, "/* The engine may define the following macros:\n");
5062 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5063 for (i = 0;i < SHADERMODE_COUNT;i++)
5064 FS_Print(file, glslshadermodeinfo[i].pretext);
5065 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5066 FS_Print(file, shaderpermutationinfo[i].pretext);
5067 FS_Print(file, "*/\n");
5068 FS_Print(file, builtinshaderstring);
5070 Con_Printf("glsl/default.glsl written\n");
5073 Con_Printf("failed to write to glsl/default.glsl\n");
5076 file = FS_OpenRealFile("cg/default.cg", "w", false);
5079 FS_Print(file, "/* The engine may define the following macros:\n");
5080 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5081 for (i = 0;i < SHADERMODE_COUNT;i++)
5082 FS_Print(file, cgshadermodeinfo[i].pretext);
5083 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5084 FS_Print(file, shaderpermutationinfo[i].pretext);
5085 FS_Print(file, "*/\n");
5086 FS_Print(file, builtincgshaderstring);
5088 Con_Printf("cg/default.cg written\n");
5091 Con_Printf("failed to write to cg/default.cg\n");
5095 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5098 FS_Print(file, "/* The engine may define the following macros:\n");
5099 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5100 for (i = 0;i < SHADERMODE_COUNT;i++)
5101 FS_Print(file, hlslshadermodeinfo[i].pretext);
5102 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5103 FS_Print(file, shaderpermutationinfo[i].pretext);
5104 FS_Print(file, "*/\n");
5105 FS_Print(file, builtincgshaderstring);
5107 Con_Printf("hlsl/default.hlsl written\n");
5110 Con_Printf("failed to write to hlsl/default.hlsl\n");
5114 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5117 texturemode = GL_MODULATE;
5118 switch (vid.renderpath)
5120 case RENDERPATH_D3D9:
5122 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5123 R_Mesh_TexBind(GL20TU_FIRST , first );
5124 R_Mesh_TexBind(GL20TU_SECOND, second);
5127 case RENDERPATH_D3D10:
5128 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5130 case RENDERPATH_D3D11:
5131 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5133 case RENDERPATH_GL20:
5134 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5135 R_Mesh_TexBind(GL20TU_FIRST , first );
5136 R_Mesh_TexBind(GL20TU_SECOND, second);
5138 case RENDERPATH_CGGL:
5141 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5142 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5143 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5146 case RENDERPATH_GL13:
5147 R_Mesh_TexBind(0, first );
5148 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5149 R_Mesh_TexBind(1, second);
5151 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5153 case RENDERPATH_GL11:
5154 R_Mesh_TexBind(0, first );
5159 void R_SetupShader_DepthOrShadow(void)
5161 switch (vid.renderpath)
5163 case RENDERPATH_D3D9:
5165 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5168 case RENDERPATH_D3D10:
5169 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5171 case RENDERPATH_D3D11:
5172 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5174 case RENDERPATH_GL20:
5175 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5177 case RENDERPATH_CGGL:
5179 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5182 case RENDERPATH_GL13:
5183 R_Mesh_TexBind(0, 0);
5184 R_Mesh_TexBind(1, 0);
5186 case RENDERPATH_GL11:
5187 R_Mesh_TexBind(0, 0);
5192 void R_SetupShader_ShowDepth(void)
5194 switch (vid.renderpath)
5196 case RENDERPATH_D3D9:
5198 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5201 case RENDERPATH_D3D10:
5202 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5204 case RENDERPATH_D3D11:
5205 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5207 case RENDERPATH_GL20:
5208 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5210 case RENDERPATH_CGGL:
5212 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5215 case RENDERPATH_GL13:
5217 case RENDERPATH_GL11:
5222 extern qboolean r_shadow_usingdeferredprepass;
5223 extern cvar_t r_shadow_deferred_8bitrange;
5224 extern rtexture_t *r_shadow_attenuationgradienttexture;
5225 extern rtexture_t *r_shadow_attenuation2dtexture;
5226 extern rtexture_t *r_shadow_attenuation3dtexture;
5227 extern qboolean r_shadow_usingshadowmap2d;
5228 extern qboolean r_shadow_usingshadowmaportho;
5229 extern float r_shadow_shadowmap_texturescale[2];
5230 extern float r_shadow_shadowmap_parameters[4];
5231 extern qboolean r_shadow_shadowmapvsdct;
5232 extern qboolean r_shadow_shadowmapsampler;
5233 extern int r_shadow_shadowmappcf;
5234 extern rtexture_t *r_shadow_shadowmap2dtexture;
5235 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5236 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5237 extern matrix4x4_t r_shadow_shadowmapmatrix;
5238 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5239 extern int r_shadow_prepass_width;
5240 extern int r_shadow_prepass_height;
5241 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5242 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5243 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5244 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5245 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5246 extern cvar_t gl_mesh_separatearrays;
5247 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5249 // a blendfunc allows colormod if:
5250 // a) it can never keep the destination pixel invariant, or
5251 // b) it can keep the destination pixel invariant, and still can do so if colormodded
5252 // this is to prevent unintended side effects from colormod
5255 // IF there is a (s, sa) for which for all (d, da),
5256 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5257 // THEN, for this (s, sa) and all (colormod, d, da):
5258 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5259 // OBVIOUSLY, this means that
5260 // s*colormod * src(s*colormod, d, sa, da) = 0
5261 // dst(s*colormod, d, sa, da) = 1
5263 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5265 // main condition to leave dst color invariant:
5266 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5268 // s * 0 + d * dst(s, d, sa, da) == d
5269 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5270 // => colormod is a problem for GL_SRC_COLOR only
5272 // s + d * dst(s, d, sa, da) == d
5274 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5275 // => colormod is never problematic for these
5276 // src == GL_SRC_COLOR:
5277 // s*s + d * dst(s, d, sa, da) == d
5279 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5280 // => colormod is never problematic for these
5281 // src == GL_ONE_MINUS_SRC_COLOR:
5282 // s*(1-s) + d * dst(s, d, sa, da) == d
5283 // => s == 0 or s == 1
5284 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5285 // => colormod is a problem for GL_SRC_COLOR only
5286 // src == GL_DST_COLOR
5287 // s*d + d * dst(s, d, sa, da) == d
5289 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5290 // => colormod is always a problem
5293 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5294 // => colormod is never problematic for these
5295 // => BUT, we do not know s! We must assume it is problematic
5296 // then... except in GL_ONE case, where we know all invariant
5298 // src == GL_ONE_MINUS_DST_COLOR
5299 // s*(1-d) + d * dst(s, d, sa, da) == d
5300 // => s == 0 (1-d is impossible to handle for our desired result)
5301 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302 // => colormod is never problematic for these
5303 // src == GL_SRC_ALPHA
5304 // s*sa + d * dst(s, d, sa, da) == d
5305 // => s == 0, or sa == 0
5306 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307 // => colormod breaks in the case GL_SRC_COLOR only
5308 // src == GL_ONE_MINUS_SRC_ALPHA
5309 // s*(1-sa) + d * dst(s, d, sa, da) == d
5310 // => s == 0, or sa == 1
5311 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312 // => colormod breaks in the case GL_SRC_COLOR only
5313 // src == GL_DST_ALPHA
5314 // s*da + d * dst(s, d, sa, da) == d
5316 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5317 // => colormod is never problematic for these
5322 case GL_ONE_MINUS_SRC_COLOR:
5324 case GL_ONE_MINUS_SRC_ALPHA:
5325 if(dst == GL_SRC_COLOR)
5330 case GL_ONE_MINUS_DST_COLOR:
5332 case GL_ONE_MINUS_DST_ALPHA:
5342 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)
5344 // select a permutation of the lighting shader appropriate to this
5345 // combination of texture, entity, light source, and fogging, only use the
5346 // minimum features necessary to avoid wasting rendering time in the
5347 // fragment shader on features that are not being used
5348 unsigned int permutation = 0;
5349 unsigned int mode = 0;
5350 qboolean allow_colormod;
5351 static float dummy_colormod[3] = {1, 1, 1};
5352 float *colormod = rsurface.colormod;
5354 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5355 if (rsurfacepass == RSURFPASS_BACKGROUND)
5357 // distorted background
5358 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5360 mode = SHADERMODE_WATER;
5361 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5362 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5363 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5364 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5366 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5368 mode = SHADERMODE_REFRACTION;
5369 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5370 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5374 mode = SHADERMODE_GENERIC;
5375 permutation |= SHADERPERMUTATION_DIFFUSE;
5376 GL_BlendFunc(GL_ONE, GL_ZERO);
5377 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5379 GL_AlphaTest(false);
5381 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5383 if (r_glsl_offsetmapping.integer)
5385 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5386 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5387 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5388 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5389 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5391 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5392 if (r_glsl_offsetmapping_reliefmapping.integer)
5393 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5396 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5397 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5399 permutation |= SHADERPERMUTATION_ALPHAKILL;
5400 // normalmap (deferred prepass), may use alpha test on diffuse
5401 mode = SHADERMODE_DEFERREDGEOMETRY;
5402 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5403 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5404 GL_AlphaTest(false);
5405 GL_BlendFunc(GL_ONE, GL_ZERO);
5406 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5408 else if (rsurfacepass == RSURFPASS_RTLIGHT)
5410 if (r_glsl_offsetmapping.integer)
5412 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5413 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5415 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5416 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5418 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5419 if (r_glsl_offsetmapping_reliefmapping.integer)
5420 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5423 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5424 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5426 mode = SHADERMODE_LIGHTSOURCE;
5427 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5428 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5429 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5430 permutation |= SHADERPERMUTATION_CUBEFILTER;
5431 if (diffusescale > 0)
5432 permutation |= SHADERPERMUTATION_DIFFUSE;
5433 if (specularscale > 0)
5434 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5435 if (r_refdef.fogenabled)
5436 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5437 if (rsurface.texture->colormapping)
5438 permutation |= SHADERPERMUTATION_COLORMAPPING;
5439 if (r_shadow_usingshadowmap2d)
5441 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5442 if(r_shadow_shadowmapvsdct)
5443 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5445 if (r_shadow_shadowmapsampler)
5446 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5447 if (r_shadow_shadowmappcf > 1)
5448 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5449 else if (r_shadow_shadowmappcf)
5450 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5452 if (rsurface.texture->reflectmasktexture)
5453 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5454 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5455 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5456 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5458 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5460 if (r_glsl_offsetmapping.integer)
5462 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5463 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5464 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5465 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5466 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5468 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5469 if (r_glsl_offsetmapping_reliefmapping.integer)
5470 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5473 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5474 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5475 // unshaded geometry (fullbright or ambient model lighting)
5476 mode = SHADERMODE_FLATCOLOR;
5477 ambientscale = diffusescale = specularscale = 0;
5478 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5479 permutation |= SHADERPERMUTATION_GLOW;
5480 if (r_refdef.fogenabled)
5481 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5482 if (rsurface.texture->colormapping)
5483 permutation |= SHADERPERMUTATION_COLORMAPPING;
5484 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5486 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5487 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5489 if (r_shadow_shadowmapsampler)
5490 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5491 if (r_shadow_shadowmappcf > 1)
5492 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5493 else if (r_shadow_shadowmappcf)
5494 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5496 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5497 permutation |= SHADERPERMUTATION_REFLECTION;
5498 if (rsurface.texture->reflectmasktexture)
5499 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5500 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5501 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5502 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5504 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5506 if (r_glsl_offsetmapping.integer)
5508 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5509 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5510 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5511 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5512 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5514 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5515 if (r_glsl_offsetmapping_reliefmapping.integer)
5516 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5519 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5520 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5521 // directional model lighting
5522 mode = SHADERMODE_LIGHTDIRECTION;
5523 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5524 permutation |= SHADERPERMUTATION_GLOW;
5525 permutation |= SHADERPERMUTATION_DIFFUSE;
5526 if (specularscale > 0)
5527 permutation |= SHADERPERMUTATION_SPECULAR;
5528 if (r_refdef.fogenabled)
5529 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5530 if (rsurface.texture->colormapping)
5531 permutation |= SHADERPERMUTATION_COLORMAPPING;
5532 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5534 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5535 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5537 if (r_shadow_shadowmapsampler)
5538 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5539 if (r_shadow_shadowmappcf > 1)
5540 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5541 else if (r_shadow_shadowmappcf)
5542 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5544 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5545 permutation |= SHADERPERMUTATION_REFLECTION;
5546 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5547 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5548 if (rsurface.texture->reflectmasktexture)
5549 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5550 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5551 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5552 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5554 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5556 if (r_glsl_offsetmapping.integer)
5558 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5559 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5560 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5561 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5562 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5564 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5565 if (r_glsl_offsetmapping_reliefmapping.integer)
5566 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5569 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5570 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5571 // ambient model lighting
5572 mode = SHADERMODE_LIGHTDIRECTION;
5573 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5574 permutation |= SHADERPERMUTATION_GLOW;
5575 if (r_refdef.fogenabled)
5576 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5577 if (rsurface.texture->colormapping)
5578 permutation |= SHADERPERMUTATION_COLORMAPPING;
5579 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5581 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5582 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5584 if (r_shadow_shadowmapsampler)
5585 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5586 if (r_shadow_shadowmappcf > 1)
5587 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5588 else if (r_shadow_shadowmappcf)
5589 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5591 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5592 permutation |= SHADERPERMUTATION_REFLECTION;
5593 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5594 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5595 if (rsurface.texture->reflectmasktexture)
5596 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5597 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5598 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5599 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5603 if (r_glsl_offsetmapping.integer)
5605 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5606 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5607 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5608 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5609 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5611 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5612 if (r_glsl_offsetmapping_reliefmapping.integer)
5613 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5617 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5619 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5620 permutation |= SHADERPERMUTATION_GLOW;
5621 if (r_refdef.fogenabled)
5622 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5623 if (rsurface.texture->colormapping)
5624 permutation |= SHADERPERMUTATION_COLORMAPPING;
5625 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5627 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5628 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5630 if (r_shadow_shadowmapsampler)
5631 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5632 if (r_shadow_shadowmappcf > 1)
5633 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5634 else if (r_shadow_shadowmappcf)
5635 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5638 permutation |= SHADERPERMUTATION_REFLECTION;
5639 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5640 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5641 if (rsurface.texture->reflectmasktexture)
5642 permutation |= SHADERPERMUTATION_REFLECTCUBE;
5643 if (FAKELIGHT_ENABLED)
5645 // fake lightmapping (q1bsp, q3bsp, fullbright map)
5646 mode = SHADERMODE_FAKELIGHT;
5647 permutation |= SHADERPERMUTATION_DIFFUSE;
5648 if (specularscale > 0)
5649 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5651 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5653 // deluxemapping (light direction texture)
5654 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5655 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5657 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5658 permutation |= SHADERPERMUTATION_DIFFUSE;
5659 if (specularscale > 0)
5660 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5662 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5664 // fake deluxemapping (uniform light direction in tangentspace)
5665 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5666 permutation |= SHADERPERMUTATION_DIFFUSE;
5667 if (specularscale > 0)
5668 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5670 else if (rsurface.uselightmaptexture)
5672 // ordinary lightmapping (q1bsp, q3bsp)
5673 mode = SHADERMODE_LIGHTMAP;
5677 // ordinary vertex coloring (q3bsp)
5678 mode = SHADERMODE_VERTEXCOLOR;
5680 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5681 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5682 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5685 colormod = dummy_colormod;
5686 switch(vid.renderpath)
5688 case RENDERPATH_D3D9:
5690 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);
5691 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5692 R_SetupShader_SetPermutationHLSL(mode, permutation);
5693 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5694 if (mode == SHADERMODE_LIGHTSOURCE)
5696 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5697 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5701 if (mode == SHADERMODE_LIGHTDIRECTION)
5703 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5706 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5707 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5708 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5709 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5710 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5712 if (mode == SHADERMODE_LIGHTSOURCE)
5714 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5715 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5716 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5717 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5718 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5720 // additive passes are only darkened by fog, not tinted
5721 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5722 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5726 if (mode == SHADERMODE_FLATCOLOR)
5728 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5730 else if (mode == SHADERMODE_LIGHTDIRECTION)
5732 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]);
5733 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5734 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);
5735 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);
5736 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5737 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5738 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5742 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5743 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5744 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);
5745 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);
5746 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5748 // additive passes are only darkened by fog, not tinted
5749 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5750 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5752 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5753 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);
5754 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5755 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5756 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5757 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5758 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5759 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5760 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5761 if (mode == SHADERMODE_WATER)
5762 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5764 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5765 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5766 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5767 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));
5768 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5769 if (rsurface.texture->pantstexture)
5770 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5772 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5773 if (rsurface.texture->shirttexture)
5774 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5776 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5777 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5778 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5779 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5780 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5781 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5782 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5783 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5785 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5786 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5787 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5788 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5789 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5790 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5791 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5792 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5793 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5794 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5795 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5796 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5797 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5798 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5799 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5800 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5801 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5802 if (rsurfacepass == RSURFPASS_BACKGROUND)
5804 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5805 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5806 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5810 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5812 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5813 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5814 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5815 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5816 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5818 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5819 if (rsurface.rtlight)
5821 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5822 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5827 case RENDERPATH_D3D10:
5828 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5830 case RENDERPATH_D3D11:
5831 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5833 case RENDERPATH_GL20:
5834 if (gl_mesh_separatearrays.integer)
5836 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);
5837 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5838 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5839 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5840 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5841 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5842 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5843 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5847 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);
5848 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5850 R_SetupShader_SetPermutationGLSL(mode, permutation);
5851 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5852 if (mode == SHADERMODE_LIGHTSOURCE)
5854 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5855 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5856 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5857 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5858 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5859 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);
5861 // additive passes are only darkened by fog, not tinted
5862 if (r_glsl_permutation->loc_FogColor >= 0)
5863 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5864 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5868 if (mode == SHADERMODE_FLATCOLOR)
5870 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5872 else if (mode == SHADERMODE_LIGHTDIRECTION)
5874 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]);
5875 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]);
5876 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);
5877 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);
5878 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);
5879 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]);
5880 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]);
5884 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]);
5885 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]);
5886 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);
5887 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);
5888 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);
5890 // additive passes are only darkened by fog, not tinted
5891 if (r_glsl_permutation->loc_FogColor >= 0)
5893 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5894 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5896 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5898 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);
5899 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]);
5900 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]);
5901 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]);
5902 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]);
5903 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5904 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5905 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5906 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]);
5908 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5909 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5910 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5911 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]);
5912 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]);
5914 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5915 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));
5916 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5917 if (r_glsl_permutation->loc_Color_Pants >= 0)
5919 if (rsurface.texture->pantstexture)
5920 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5922 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5924 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5926 if (rsurface.texture->shirttexture)
5927 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5929 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5931 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]);
5932 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5933 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5934 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5935 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5936 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]);
5937 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5939 // if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_texture_white );
5940 // if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_texture_white );
5941 // if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS , r_texture_gammaramps );
5942 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
5943 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
5944 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
5945 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
5946 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
5947 if (r_glsl_permutation->loc_Texture_SecondaryColor >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
5948 if (r_glsl_permutation->loc_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
5949 if (r_glsl_permutation->loc_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
5950 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
5951 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
5952 if (r_glsl_permutation->loc_Texture_ReflectMask >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
5953 if (r_glsl_permutation->loc_Texture_ReflectCube >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5954 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
5955 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
5956 if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5957 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5958 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
5959 if (rsurfacepass == RSURFPASS_BACKGROUND)
5961 if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5962 else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5963 if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5967 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5969 // if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
5970 // if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
5971 if (r_glsl_permutation->loc_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
5972 if (r_glsl_permutation->loc_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
5973 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5975 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture );
5976 if (rsurface.rtlight)
5978 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
5979 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
5984 case RENDERPATH_CGGL:
5986 if (gl_mesh_separatearrays.integer)
5988 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);
5989 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5990 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5991 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5992 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5993 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5994 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5995 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5999 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);
6000 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6002 R_SetupShader_SetPermutationCG(mode, permutation);
6003 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6004 if (mode == SHADERMODE_LIGHTSOURCE)
6006 if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6007 if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6011 if (mode == SHADERMODE_LIGHTDIRECTION)
6013 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
6016 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6017 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6018 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6019 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6020 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
6023 if (mode == SHADERMODE_LIGHTSOURCE)
6025 if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6026 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6027 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6028 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6029 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
6031 // additive passes are only darkened by fog, not tinted
6032 if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6033 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6037 if (mode == SHADERMODE_FLATCOLOR)
6039 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6041 else if (mode == SHADERMODE_LIGHTDIRECTION)
6043 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
6044 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
6045 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
6046 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
6047 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
6048 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
6049 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
6053 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
6054 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
6055 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
6056 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
6057 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
6059 // additive passes are only darkened by fog, not tinted
6060 if (r_cg_permutation->fp_FogColor)
6062 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6063 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6065 cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6068 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
6069 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
6070 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
6071 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
6072 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
6073 if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6074 if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6075 if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6076 if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6078 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
6079 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
6080 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6081 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
6082 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6083 if (r_cg_permutation->fp_Color_Pants)
6085 if (rsurface.texture->pantstexture)
6086 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6088 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6091 if (r_cg_permutation->fp_Color_Shirt)
6093 if (rsurface.texture->shirttexture)
6094 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6096 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6099 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
6100 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6101 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6102 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6103 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6104 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
6105 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6107 // if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_texture_white );CHECKCGERROR
6108 // if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_texture_white );CHECKCGERROR
6109 // if (r_cg_permutation->fp_Texture_GammaRamps ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps , r_texture_gammaramps );CHECKCGERROR
6110 if (r_cg_permutation->fp_Texture_Normal ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal , rsurface.texture->nmaptexture );CHECKCGERROR
6111 if (r_cg_permutation->fp_Texture_Color ) CG_BindTexture(r_cg_permutation->fp_Texture_Color , rsurface.texture->basetexture );CHECKCGERROR
6112 if (r_cg_permutation->fp_Texture_Gloss ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss , rsurface.texture->glosstexture );CHECKCGERROR
6113 if (r_cg_permutation->fp_Texture_Glow ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow , rsurface.texture->glowtexture );CHECKCGERROR
6114 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture );CHECKCGERROR
6115 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );CHECKCGERROR
6116 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );CHECKCGERROR
6117 if (r_cg_permutation->fp_Texture_SecondaryGlow ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );CHECKCGERROR
6118 if (r_cg_permutation->fp_Texture_Pants ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants , rsurface.texture->pantstexture );CHECKCGERROR
6119 if (r_cg_permutation->fp_Texture_Shirt ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt , rsurface.texture->shirttexture );CHECKCGERROR
6120 if (r_cg_permutation->fp_Texture_ReflectMask ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask , rsurface.texture->reflectmasktexture );CHECKCGERROR
6121 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
6122 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture );CHECKCGERROR
6123 if (r_cg_permutation->fp_Texture_FogMask ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask , r_texture_fogattenuation );CHECKCGERROR
6124 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6125 if (r_cg_permutation->fp_Texture_Deluxemap ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6126 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6127 if (rsurfacepass == RSURFPASS_BACKGROUND)
6129 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
6130 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
6131 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
6135 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
6137 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6138 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6139 if (r_cg_permutation->fp_Texture_ScreenDiffuse ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );CHECKCGERROR
6140 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );CHECKCGERROR
6141 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6143 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6144 if (rsurface.rtlight)
6146 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6147 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6154 case RENDERPATH_GL13:
6155 case RENDERPATH_GL11:
6160 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6162 // select a permutation of the lighting shader appropriate to this
6163 // combination of texture, entity, light source, and fogging, only use the
6164 // minimum features necessary to avoid wasting rendering time in the
6165 // fragment shader on features that are not being used
6166 unsigned int permutation = 0;
6167 unsigned int mode = 0;
6168 const float *lightcolorbase = rtlight->currentcolor;
6169 float ambientscale = rtlight->ambientscale;
6170 float diffusescale = rtlight->diffusescale;
6171 float specularscale = rtlight->specularscale;
6172 // this is the location of the light in view space
6173 vec3_t viewlightorigin;
6174 // this transforms from view space (camera) to light space (cubemap)
6175 matrix4x4_t viewtolight;
6176 matrix4x4_t lighttoview;
6177 float viewtolight16f[16];
6178 float range = 1.0f / r_shadow_deferred_8bitrange.value;
6180 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6181 if (rtlight->currentcubemap != r_texture_whitecube)
6182 permutation |= SHADERPERMUTATION_CUBEFILTER;
6183 if (diffusescale > 0)
6184 permutation |= SHADERPERMUTATION_DIFFUSE;
6185 if (specularscale > 0)
6186 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6187 if (r_shadow_usingshadowmap2d)
6189 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6190 if (r_shadow_shadowmapvsdct)
6191 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6193 if (r_shadow_shadowmapsampler)
6194 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6195 if (r_shadow_shadowmappcf > 1)
6196 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6197 else if (r_shadow_shadowmappcf)
6198 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6200 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6201 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6202 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6203 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6204 switch(vid.renderpath)
6206 case RENDERPATH_D3D9:
6208 R_SetupShader_SetPermutationHLSL(mode, permutation);
6209 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6210 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6211 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
6212 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
6213 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6214 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6215 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6216 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6217 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6218 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6220 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6221 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
6222 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6223 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6224 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
6225 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6228 case RENDERPATH_D3D10:
6229 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6231 case RENDERPATH_D3D11:
6232 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6234 case RENDERPATH_GL20:
6235 R_SetupShader_SetPermutationGLSL(mode, permutation);
6236 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6237 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
6238 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);
6239 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);
6240 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);
6241 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]);
6242 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]);
6243 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) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6244 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]);
6245 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6247 if (r_glsl_permutation->loc_Texture_Attenuation >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
6248 if (r_glsl_permutation->loc_Texture_ScreenDepth >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
6249 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
6250 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
6251 if (r_glsl_permutation->loc_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
6252 if (r_glsl_permutation->loc_Texture_CubeProjection >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
6254 case RENDERPATH_CGGL:
6256 R_SetupShader_SetPermutationCG(mode, permutation);
6257 if (r_cg_permutation->fp_LightPosition ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6258 if (r_cg_permutation->fp_ViewToLight ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6259 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
6260 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
6261 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
6262 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
6263 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
6264 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) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6265 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
6266 if (r_cg_permutation->fp_PixelToScreenTexCoord ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6268 if (r_cg_permutation->fp_Texture_Attenuation ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation , r_shadow_attenuationgradienttexture );CHECKCGERROR
6269 if (r_cg_permutation->fp_Texture_ScreenDepth ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );CHECKCGERROR
6270 if (r_cg_permutation->fp_Texture_ScreenNormalMap ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture );CHECKCGERROR
6271 if (r_cg_permutation->fp_Texture_Cube ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube , rsurface.rtlight->currentcubemap );CHECKCGERROR
6272 if (r_cg_permutation->fp_Texture_ShadowMap2D ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );CHECKCGERROR
6273 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );CHECKCGERROR
6276 case RENDERPATH_GL13:
6277 case RENDERPATH_GL11:
6282 #define SKINFRAME_HASH 1024
6286 int loadsequence; // incremented each level change
6287 memexpandablearray_t array;
6288 skinframe_t *hash[SKINFRAME_HASH];
6291 r_skinframe_t r_skinframe;
6293 void R_SkinFrame_PrepareForPurge(void)
6295 r_skinframe.loadsequence++;
6296 // wrap it without hitting zero
6297 if (r_skinframe.loadsequence >= 200)
6298 r_skinframe.loadsequence = 1;
6301 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6305 // mark the skinframe as used for the purging code
6306 skinframe->loadsequence = r_skinframe.loadsequence;
6309 void R_SkinFrame_Purge(void)
6313 for (i = 0;i < SKINFRAME_HASH;i++)
6315 for (s = r_skinframe.hash[i];s;s = s->next)
6317 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6319 if (s->merged == s->base)
6321 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6322 R_PurgeTexture(s->stain );s->stain = NULL;
6323 R_PurgeTexture(s->merged);s->merged = NULL;
6324 R_PurgeTexture(s->base );s->base = NULL;
6325 R_PurgeTexture(s->pants );s->pants = NULL;
6326 R_PurgeTexture(s->shirt );s->shirt = NULL;
6327 R_PurgeTexture(s->nmap );s->nmap = NULL;
6328 R_PurgeTexture(s->gloss );s->gloss = NULL;
6329 R_PurgeTexture(s->glow );s->glow = NULL;
6330 R_PurgeTexture(s->fog );s->fog = NULL;
6331 R_PurgeTexture(s->reflect);s->reflect = NULL;
6332 s->loadsequence = 0;
6338 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6340 char basename[MAX_QPATH];
6342 Image_StripImageExtension(name, basename, sizeof(basename));
6344 if( last == NULL ) {
6346 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6347 item = r_skinframe.hash[hashindex];
6352 // linearly search through the hash bucket
6353 for( ; item ; item = item->next ) {
6354 if( !strcmp( item->basename, basename ) ) {
6361 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6365 char basename[MAX_QPATH];
6367 Image_StripImageExtension(name, basename, sizeof(basename));
6369 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6370 for (item = r_skinframe.hash[hashindex];item;item = item->next)
6371 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6375 rtexture_t *dyntexture;
6376 // check whether its a dynamic texture
6377 dyntexture = CL_GetDynTexture( basename );
6378 if (!add && !dyntexture)
6380 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6381 memset(item, 0, sizeof(*item));
6382 strlcpy(item->basename, basename, sizeof(item->basename));
6383 item->base = dyntexture; // either NULL or dyntexture handle
6384 item->textureflags = textureflags;
6385 item->comparewidth = comparewidth;
6386 item->compareheight = compareheight;
6387 item->comparecrc = comparecrc;
6388 item->next = r_skinframe.hash[hashindex];
6389 r_skinframe.hash[hashindex] = item;
6391 else if( item->base == NULL )
6393 rtexture_t *dyntexture;
6394 // check whether its a dynamic texture
6395 // 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]
6396 dyntexture = CL_GetDynTexture( basename );
6397 item->base = dyntexture; // either NULL or dyntexture handle
6400 R_SkinFrame_MarkUsed(item);
6404 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6406 unsigned long long avgcolor[5], wsum; \
6414 for(pix = 0; pix < cnt; ++pix) \
6417 for(comp = 0; comp < 3; ++comp) \
6419 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6422 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6424 for(comp = 0; comp < 3; ++comp) \
6425 avgcolor[comp] += getpixel * w; \
6428 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6429 avgcolor[4] += getpixel; \
6431 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6433 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6434 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6435 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6436 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6439 extern cvar_t gl_picmip;
6440 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6443 unsigned char *pixels;
6444 unsigned char *bumppixels;
6445 unsigned char *basepixels = NULL;
6446 int basepixels_width = 0;
6447 int basepixels_height = 0;
6448 skinframe_t *skinframe;
6449 rtexture_t *ddsbase = NULL;
6450 qboolean ddshasalpha = false;
6451 float ddsavgcolor[4];
6452 char basename[MAX_QPATH];
6453 int miplevel = R_PicmipForFlags(textureflags);
6454 int savemiplevel = miplevel;
6457 if (cls.state == ca_dedicated)
6460 // return an existing skinframe if already loaded
6461 // if loading of the first image fails, don't make a new skinframe as it
6462 // would cause all future lookups of this to be missing
6463 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6464 if (skinframe && skinframe->base)
6467 Image_StripImageExtension(name, basename, sizeof(basename));
6469 // check for DDS texture file first
6470 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6472 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6473 if (basepixels == NULL)
6477 // FIXME handle miplevel
6479 if (developer_loading.integer)
6480 Con_Printf("loading skin \"%s\"\n", name);
6482 // we've got some pixels to store, so really allocate this new texture now
6484 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6485 skinframe->stain = NULL;
6486 skinframe->merged = NULL;
6487 skinframe->base = NULL;
6488 skinframe->pants = NULL;
6489 skinframe->shirt = NULL;
6490 skinframe->nmap = NULL;
6491 skinframe->gloss = NULL;
6492 skinframe->glow = NULL;
6493 skinframe->fog = NULL;
6494 skinframe->reflect = NULL;
6495 skinframe->hasalpha = false;
6499 skinframe->base = ddsbase;
6500 skinframe->hasalpha = ddshasalpha;
6501 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6502 if (r_loadfog && skinframe->hasalpha)
6503 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6504 //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]);
6508 basepixels_width = image_width;
6509 basepixels_height = image_height;
6510 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);
6511 if (textureflags & TEXF_ALPHA)
6513 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6515 if (basepixels[j] < 255)
6517 skinframe->hasalpha = true;
6521 if (r_loadfog && skinframe->hasalpha)
6523 // has transparent pixels
6524 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6525 for (j = 0;j < image_width * image_height * 4;j += 4)
6530 pixels[j+3] = basepixels[j+3];
6532 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);
6536 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6537 //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]);
6538 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6539 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6540 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6541 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6546 mymiplevel = savemiplevel;
6547 if (r_loadnormalmap)
6548 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);
6549 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6551 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6552 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6553 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6554 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6557 // _norm is the name used by tenebrae and has been adopted as standard
6558 if (r_loadnormalmap && skinframe->nmap == NULL)
6560 mymiplevel = savemiplevel;
6561 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6563 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);
6567 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6569 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6570 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6571 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);
6573 Mem_Free(bumppixels);
6575 else if (r_shadow_bumpscale_basetexture.value > 0)
6577 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6578 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6579 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);
6582 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6583 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6586 // _luma is supported only for tenebrae compatibility
6587 // _glow is the preferred name
6588 mymiplevel = savemiplevel;
6589 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))))
6591 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);
6592 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6593 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6594 Mem_Free(pixels);pixels = NULL;
6597 mymiplevel = savemiplevel;
6598 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6600 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);
6601 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6602 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6607 mymiplevel = savemiplevel;
6608 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6610 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);
6611 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6612 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6617 mymiplevel = savemiplevel;
6618 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6620 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);
6621 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6622 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6627 mymiplevel = savemiplevel;
6628 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6630 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);
6631 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6632 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6638 Mem_Free(basepixels);
6643 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6644 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6647 unsigned char *temp1, *temp2;
6648 skinframe_t *skinframe;
6650 if (cls.state == ca_dedicated)
6653 // if already loaded just return it, otherwise make a new skinframe
6654 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6655 if (skinframe && skinframe->base)
6658 skinframe->stain = NULL;
6659 skinframe->merged = NULL;
6660 skinframe->base = NULL;
6661 skinframe->pants = NULL;
6662 skinframe->shirt = NULL;
6663 skinframe->nmap = NULL;
6664 skinframe->gloss = NULL;
6665 skinframe->glow = NULL;
6666 skinframe->fog = NULL;
6667 skinframe->reflect = NULL;
6668 skinframe->hasalpha = false;
6670 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6674 if (developer_loading.integer)
6675 Con_Printf("loading 32bit skin \"%s\"\n", name);
6677 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6679 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6680 temp2 = temp1 + width * height * 4;
6681 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6682 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);
6685 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6686 if (textureflags & TEXF_ALPHA)
6688 for (i = 3;i < width * height * 4;i += 4)
6690 if (skindata[i] < 255)
6692 skinframe->hasalpha = true;
6696 if (r_loadfog && skinframe->hasalpha)
6698 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6699 memcpy(fogpixels, skindata, width * height * 4);
6700 for (i = 0;i < width * height * 4;i += 4)
6701 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6702 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6703 Mem_Free(fogpixels);
6707 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6708 //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]);
6713 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6717 skinframe_t *skinframe;
6719 if (cls.state == ca_dedicated)
6722 // if already loaded just return it, otherwise make a new skinframe
6723 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6724 if (skinframe && skinframe->base)
6727 skinframe->stain = NULL;
6728 skinframe->merged = NULL;
6729 skinframe->base = NULL;
6730 skinframe->pants = NULL;
6731 skinframe->shirt = NULL;
6732 skinframe->nmap = NULL;
6733 skinframe->gloss = NULL;
6734 skinframe->glow = NULL;
6735 skinframe->fog = NULL;
6736 skinframe->reflect = NULL;
6737 skinframe->hasalpha = false;
6739 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6743 if (developer_loading.integer)
6744 Con_Printf("loading quake skin \"%s\"\n", name);
6746 // 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)
6747 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6748 memcpy(skinframe->qpixels, skindata, width*height);
6749 skinframe->qwidth = width;
6750 skinframe->qheight = height;
6753 for (i = 0;i < width * height;i++)
6754 featuresmask |= palette_featureflags[skindata[i]];
6756 skinframe->hasalpha = false;
6757 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6758 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6759 skinframe->qgeneratemerged = true;
6760 skinframe->qgeneratebase = skinframe->qhascolormapping;
6761 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6763 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6764 //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]);
6769 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6773 unsigned char *skindata;
6775 if (!skinframe->qpixels)
6778 if (!skinframe->qhascolormapping)
6779 colormapped = false;
6783 if (!skinframe->qgeneratebase)
6788 if (!skinframe->qgeneratemerged)
6792 width = skinframe->qwidth;
6793 height = skinframe->qheight;
6794 skindata = skinframe->qpixels;
6796 if (skinframe->qgeneratenmap)
6798 unsigned char *temp1, *temp2;
6799 skinframe->qgeneratenmap = false;
6800 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6801 temp2 = temp1 + width * height * 4;
6802 // use either a custom palette or the quake palette
6803 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6804 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6805 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);
6809 if (skinframe->qgenerateglow)
6811 skinframe->qgenerateglow = false;
6812 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6817 skinframe->qgeneratebase = false;
6818 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);
6819 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6820 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6824 skinframe->qgeneratemerged = false;
6825 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);
6828 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6830 Mem_Free(skinframe->qpixels);
6831 skinframe->qpixels = NULL;
6835 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)
6838 skinframe_t *skinframe;
6840 if (cls.state == ca_dedicated)
6843 // if already loaded just return it, otherwise make a new skinframe
6844 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6845 if (skinframe && skinframe->base)
6848 skinframe->stain = NULL;
6849 skinframe->merged = NULL;
6850 skinframe->base = NULL;
6851 skinframe->pants = NULL;
6852 skinframe->shirt = NULL;
6853 skinframe->nmap = NULL;
6854 skinframe->gloss = NULL;
6855 skinframe->glow = NULL;
6856 skinframe->fog = NULL;
6857 skinframe->reflect = NULL;
6858 skinframe->hasalpha = false;
6860 // if no data was provided, then clearly the caller wanted to get a blank skinframe
6864 if (developer_loading.integer)
6865 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6867 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6868 if (textureflags & TEXF_ALPHA)
6870 for (i = 0;i < width * height;i++)
6872 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6874 skinframe->hasalpha = true;
6878 if (r_loadfog && skinframe->hasalpha)
6879 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6882 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6883 //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]);
6888 skinframe_t *R_SkinFrame_LoadMissing(void)
6890 skinframe_t *skinframe;
6892 if (cls.state == ca_dedicated)
6895 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6896 skinframe->stain = NULL;
6897 skinframe->merged = NULL;
6898 skinframe->base = NULL;
6899 skinframe->pants = NULL;
6900 skinframe->shirt = NULL;
6901 skinframe->nmap = NULL;
6902 skinframe->gloss = NULL;
6903 skinframe->glow = NULL;
6904 skinframe->fog = NULL;
6905 skinframe->reflect = NULL;
6906 skinframe->hasalpha = false;
6908 skinframe->avgcolor[0] = rand() / RAND_MAX;
6909 skinframe->avgcolor[1] = rand() / RAND_MAX;
6910 skinframe->avgcolor[2] = rand() / RAND_MAX;
6911 skinframe->avgcolor[3] = 1;
6916 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6917 typedef struct suffixinfo_s
6920 qboolean flipx, flipy, flipdiagonal;
6923 static suffixinfo_t suffix[3][6] =
6926 {"px", false, false, false},
6927 {"nx", false, false, false},
6928 {"py", false, false, false},
6929 {"ny", false, false, false},
6930 {"pz", false, false, false},
6931 {"nz", false, false, false}
6934 {"posx", false, false, false},
6935 {"negx", false, false, false},
6936 {"posy", false, false, false},
6937 {"negy", false, false, false},
6938 {"posz", false, false, false},
6939 {"negz", false, false, false}
6942 {"rt", true, false, true},
6943 {"lf", false, true, true},
6944 {"ft", true, true, false},
6945 {"bk", false, false, false},
6946 {"up", true, false, true},
6947 {"dn", true, false, true}
6951 static int componentorder[4] = {0, 1, 2, 3};
6953 rtexture_t *R_LoadCubemap(const char *basename)
6955 int i, j, cubemapsize;
6956 unsigned char *cubemappixels, *image_buffer;
6957 rtexture_t *cubemaptexture;
6959 // must start 0 so the first loadimagepixels has no requested width/height
6961 cubemappixels = NULL;
6962 cubemaptexture = NULL;
6963 // keep trying different suffix groups (posx, px, rt) until one loads
6964 for (j = 0;j < 3 && !cubemappixels;j++)
6966 // load the 6 images in the suffix group
6967 for (i = 0;i < 6;i++)
6969 // generate an image name based on the base and and suffix
6970 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6972 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6974 // an image loaded, make sure width and height are equal
6975 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6977 // if this is the first image to load successfully, allocate the cubemap memory
6978 if (!cubemappixels && image_width >= 1)
6980 cubemapsize = image_width;
6981 // note this clears to black, so unavailable sides are black
6982 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6984 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6986 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);
6989 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6991 Mem_Free(image_buffer);
6995 // if a cubemap loaded, upload it
6998 if (developer_loading.integer)
6999 Con_Printf("loading cubemap \"%s\"\n", basename);
7001 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7002 Mem_Free(cubemappixels);
7006 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7007 if (developer_loading.integer)
7009 Con_Printf("(tried tried images ");
7010 for (j = 0;j < 3;j++)
7011 for (i = 0;i < 6;i++)
7012 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7013 Con_Print(" and was unable to find any of them).\n");
7016 return cubemaptexture;
7019 rtexture_t *R_GetCubemap(const char *basename)
7022 for (i = 0;i < r_texture_numcubemaps;i++)
7023 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7024 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7025 if (i >= MAX_CUBEMAPS)
7026 return r_texture_whitecube;
7027 r_texture_numcubemaps++;
7028 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7029 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7030 return r_texture_cubemaps[i].texture;
7033 void R_FreeCubemaps(void)
7036 for (i = 0;i < r_texture_numcubemaps;i++)
7038 if (developer_loading.integer)
7039 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7040 if (r_texture_cubemaps[i].texture)
7041 R_FreeTexture(r_texture_cubemaps[i].texture);
7043 r_texture_numcubemaps = 0;
7046 void R_Main_FreeViewCache(void)
7048 if (r_refdef.viewcache.entityvisible)
7049 Mem_Free(r_refdef.viewcache.entityvisible);
7050 if (r_refdef.viewcache.world_pvsbits)
7051 Mem_Free(r_refdef.viewcache.world_pvsbits);
7052 if (r_refdef.viewcache.world_leafvisible)
7053 Mem_Free(r_refdef.viewcache.world_leafvisible);
7054 if (r_refdef.viewcache.world_surfacevisible)
7055 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7056 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7059 void R_Main_ResizeViewCache(void)
7061 int numentities = r_refdef.scene.numentities;
7062 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7063 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7064 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7065 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7066 if (r_refdef.viewcache.maxentities < numentities)
7068 r_refdef.viewcache.maxentities = numentities;
7069 if (r_refdef.viewcache.entityvisible)
7070 Mem_Free(r_refdef.viewcache.entityvisible);
7071 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7073 if (r_refdef.viewcache.world_numclusters != numclusters)
7075 r_refdef.viewcache.world_numclusters = numclusters;
7076 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7077 if (r_refdef.viewcache.world_pvsbits)
7078 Mem_Free(r_refdef.viewcache.world_pvsbits);
7079 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7081 if (r_refdef.viewcache.world_numleafs != numleafs)
7083 r_refdef.viewcache.world_numleafs = numleafs;
7084 if (r_refdef.viewcache.world_leafvisible)
7085 Mem_Free(r_refdef.viewcache.world_leafvisible);
7086 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7088 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7090 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7091 if (r_refdef.viewcache.world_surfacevisible)
7092 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7093 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7097 extern rtexture_t *loadingscreentexture;
7098 void gl_main_start(void)
7100 loadingscreentexture = NULL;
7101 r_texture_blanknormalmap = NULL;
7102 r_texture_white = NULL;
7103 r_texture_grey128 = NULL;
7104 r_texture_black = NULL;
7105 r_texture_whitecube = NULL;
7106 r_texture_normalizationcube = NULL;
7107 r_texture_fogattenuation = NULL;
7108 r_texture_fogheighttexture = NULL;
7109 r_texture_gammaramps = NULL;
7110 r_texture_numcubemaps = 0;
7112 r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7113 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7115 switch(vid.renderpath)
7117 case RENDERPATH_GL20:
7118 case RENDERPATH_CGGL:
7119 case RENDERPATH_D3D9:
7120 case RENDERPATH_D3D10:
7121 case RENDERPATH_D3D11:
7122 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7123 Cvar_SetValueQuick(&gl_combine, 1);
7124 Cvar_SetValueQuick(&r_glsl, 1);
7125 r_loadnormalmap = true;
7129 case RENDERPATH_GL13:
7130 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7131 Cvar_SetValueQuick(&gl_combine, 1);
7132 Cvar_SetValueQuick(&r_glsl, 0);
7133 r_loadnormalmap = false;
7134 r_loadgloss = false;
7137 case RENDERPATH_GL11:
7138 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7139 Cvar_SetValueQuick(&gl_combine, 0);
7140 Cvar_SetValueQuick(&r_glsl, 0);
7141 r_loadnormalmap = false;
7142 r_loadgloss = false;
7148 R_FrameData_Reset();
7152 memset(r_queries, 0, sizeof(r_queries));
7154 r_qwskincache = NULL;
7155 r_qwskincache_size = 0;
7157 // set up r_skinframe loading system for textures
7158 memset(&r_skinframe, 0, sizeof(r_skinframe));
7159 r_skinframe.loadsequence = 1;
7160 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7162 r_main_texturepool = R_AllocTexturePool();
7163 R_BuildBlankTextures();
7165 if (vid.support.arb_texture_cube_map)
7168 R_BuildNormalizationCube();
7170 r_texture_fogattenuation = NULL;
7171 r_texture_fogheighttexture = NULL;
7172 r_texture_gammaramps = NULL;
7173 //r_texture_fogintensity = NULL;
7174 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7175 memset(&r_waterstate, 0, sizeof(r_waterstate));
7176 r_glsl_permutation = NULL;
7177 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7178 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7179 glslshaderstring = NULL;
7181 r_cg_permutation = NULL;
7182 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7183 Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7184 cgshaderstring = NULL;
7187 r_hlsl_permutation = NULL;
7188 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7189 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7190 hlslshaderstring = NULL;
7192 memset(&r_svbsp, 0, sizeof (r_svbsp));
7194 r_refdef.fogmasktable_density = 0;
7197 void gl_main_shutdown(void)
7200 R_FrameData_Reset();
7202 R_Main_FreeViewCache();
7204 switch(vid.renderpath)
7206 case RENDERPATH_GL11:
7207 case RENDERPATH_GL13:
7208 case RENDERPATH_GL20:
7209 case RENDERPATH_CGGL:
7211 qglDeleteQueriesARB(r_maxqueries, r_queries);
7213 case RENDERPATH_D3D9:
7214 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7216 case RENDERPATH_D3D10:
7217 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7219 case RENDERPATH_D3D11:
7220 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7226 memset(r_queries, 0, sizeof(r_queries));
7228 r_qwskincache = NULL;
7229 r_qwskincache_size = 0;
7231 // clear out the r_skinframe state
7232 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7233 memset(&r_skinframe, 0, sizeof(r_skinframe));
7236 Mem_Free(r_svbsp.nodes);
7237 memset(&r_svbsp, 0, sizeof (r_svbsp));
7238 R_FreeTexturePool(&r_main_texturepool);
7239 loadingscreentexture = NULL;
7240 r_texture_blanknormalmap = NULL;
7241 r_texture_white = NULL;
7242 r_texture_grey128 = NULL;
7243 r_texture_black = NULL;
7244 r_texture_whitecube = NULL;
7245 r_texture_normalizationcube = NULL;
7246 r_texture_fogattenuation = NULL;
7247 r_texture_fogheighttexture = NULL;
7248 r_texture_gammaramps = NULL;
7249 r_texture_numcubemaps = 0;
7250 //r_texture_fogintensity = NULL;
7251 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7252 memset(&r_waterstate, 0, sizeof(r_waterstate));
7256 extern void CL_ParseEntityLump(char *entitystring);
7257 void gl_main_newmap(void)
7259 // FIXME: move this code to client
7260 char *entities, entname[MAX_QPATH];
7262 Mem_Free(r_qwskincache);
7263 r_qwskincache = NULL;
7264 r_qwskincache_size = 0;
7267 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7268 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7270 CL_ParseEntityLump(entities);
7274 if (cl.worldmodel->brush.entities)
7275 CL_ParseEntityLump(cl.worldmodel->brush.entities);
7277 R_Main_FreeViewCache();
7279 R_FrameData_Reset();
7282 void GL_Main_Init(void)
7284 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7286 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7287 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7288 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7289 if (gamemode == GAME_NEHAHRA)
7291 Cvar_RegisterVariable (&gl_fogenable);
7292 Cvar_RegisterVariable (&gl_fogdensity);
7293 Cvar_RegisterVariable (&gl_fogred);
7294 Cvar_RegisterVariable (&gl_foggreen);
7295 Cvar_RegisterVariable (&gl_fogblue);
7296 Cvar_RegisterVariable (&gl_fogstart);
7297 Cvar_RegisterVariable (&gl_fogend);
7298 Cvar_RegisterVariable (&gl_skyclip);
7300 Cvar_RegisterVariable(&r_motionblur);
7301 Cvar_RegisterVariable(&r_motionblur_maxblur);
7302 Cvar_RegisterVariable(&r_motionblur_bmin);
7303 Cvar_RegisterVariable(&r_motionblur_vmin);
7304 Cvar_RegisterVariable(&r_motionblur_vmax);
7305 Cvar_RegisterVariable(&r_motionblur_vcoeff);
7306 Cvar_RegisterVariable(&r_motionblur_randomize);
7307 Cvar_RegisterVariable(&r_damageblur);
7308 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7309 Cvar_RegisterVariable(&r_equalize_entities_minambient);
7310 Cvar_RegisterVariable(&r_equalize_entities_by);
7311 Cvar_RegisterVariable(&r_equalize_entities_to);
7312 Cvar_RegisterVariable(&r_depthfirst);
7313 Cvar_RegisterVariable(&r_useinfinitefarclip);
7314 Cvar_RegisterVariable(&r_farclip_base);
7315 Cvar_RegisterVariable(&r_farclip_world);
7316 Cvar_RegisterVariable(&r_nearclip);
7317 Cvar_RegisterVariable(&r_showbboxes);
7318 Cvar_RegisterVariable(&r_showsurfaces);
7319 Cvar_RegisterVariable(&r_showtris);
7320 Cvar_RegisterVariable(&r_shownormals);
7321 Cvar_RegisterVariable(&r_showlighting);
7322 Cvar_RegisterVariable(&r_showshadowvolumes);
7323 Cvar_RegisterVariable(&r_showcollisionbrushes);
7324 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7325 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7326 Cvar_RegisterVariable(&r_showdisabledepthtest);
7327 Cvar_RegisterVariable(&r_drawportals);
7328 Cvar_RegisterVariable(&r_drawentities);
7329 Cvar_RegisterVariable(&r_draw2d);
7330 Cvar_RegisterVariable(&r_drawworld);
7331 Cvar_RegisterVariable(&r_cullentities_trace);
7332 Cvar_RegisterVariable(&r_cullentities_trace_samples);
7333 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7334 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7335 Cvar_RegisterVariable(&r_cullentities_trace_delay);
7336 Cvar_RegisterVariable(&r_drawviewmodel);
7337 Cvar_RegisterVariable(&r_drawexteriormodel);
7338 Cvar_RegisterVariable(&r_speeds);
7339 Cvar_RegisterVariable(&r_fullbrights);
7340 Cvar_RegisterVariable(&r_wateralpha);
7341 Cvar_RegisterVariable(&r_dynamic);
7342 Cvar_RegisterVariable(&r_fakelight);
7343 Cvar_RegisterVariable(&r_fakelight_intensity);
7344 Cvar_RegisterVariable(&r_fullbright);
7345 Cvar_RegisterVariable(&r_shadows);
7346 Cvar_RegisterVariable(&r_shadows_darken);
7347 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7348 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7349 Cvar_RegisterVariable(&r_shadows_throwdistance);
7350 Cvar_RegisterVariable(&r_shadows_throwdirection);
7351 Cvar_RegisterVariable(&r_shadows_focus);
7352 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7353 Cvar_RegisterVariable(&r_q1bsp_skymasking);
7354 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7355 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7356 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7357 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7358 Cvar_RegisterVariable(&r_fog_exp2);
7359 Cvar_RegisterVariable(&r_drawfog);
7360 Cvar_RegisterVariable(&r_transparentdepthmasking);
7361 Cvar_RegisterVariable(&r_texture_dds_load);
7362 Cvar_RegisterVariable(&r_texture_dds_save);
7363 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7364 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7365 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7366 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7367 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7368 Cvar_RegisterVariable(&r_textureunits);
7369 Cvar_RegisterVariable(&gl_combine);
7370 Cvar_RegisterVariable(&r_glsl);
7371 Cvar_RegisterVariable(&r_glsl_deluxemapping);
7372 Cvar_RegisterVariable(&r_glsl_offsetmapping);
7373 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7374 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7375 Cvar_RegisterVariable(&r_glsl_postprocess);
7376 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7377 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7378 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7379 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7380 Cvar_RegisterVariable(&r_water);
7381 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7382 Cvar_RegisterVariable(&r_water_clippingplanebias);
7383 Cvar_RegisterVariable(&r_water_refractdistort);
7384 Cvar_RegisterVariable(&r_water_reflectdistort);
7385 Cvar_RegisterVariable(&r_water_scissormode);
7386 Cvar_RegisterVariable(&r_lerpsprites);
7387 Cvar_RegisterVariable(&r_lerpmodels);
7388 Cvar_RegisterVariable(&r_lerplightstyles);
7389 Cvar_RegisterVariable(&r_waterscroll);
7390 Cvar_RegisterVariable(&r_bloom);
7391 Cvar_RegisterVariable(&r_bloom_colorscale);
7392 Cvar_RegisterVariable(&r_bloom_brighten);
7393 Cvar_RegisterVariable(&r_bloom_blur);
7394 Cvar_RegisterVariable(&r_bloom_resolution);
7395 Cvar_RegisterVariable(&r_bloom_colorexponent);
7396 Cvar_RegisterVariable(&r_bloom_colorsubtract);
7397 Cvar_RegisterVariable(&r_hdr);
7398 Cvar_RegisterVariable(&r_hdr_scenebrightness);
7399 Cvar_RegisterVariable(&r_hdr_glowintensity);
7400 Cvar_RegisterVariable(&r_hdr_range);
7401 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7402 Cvar_RegisterVariable(&developer_texturelogging);
7403 Cvar_RegisterVariable(&gl_lightmaps);
7404 Cvar_RegisterVariable(&r_test);
7405 Cvar_RegisterVariable(&r_glsl_saturation);
7406 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7407 Cvar_RegisterVariable(&r_framedatasize);
7408 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7409 Cvar_SetValue("r_fullbrights", 0);
7410 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7412 Cvar_RegisterVariable(&r_track_sprites);
7413 Cvar_RegisterVariable(&r_track_sprites_flags);
7414 Cvar_RegisterVariable(&r_track_sprites_scalew);
7415 Cvar_RegisterVariable(&r_track_sprites_scaleh);
7416 Cvar_RegisterVariable(&r_overheadsprites_perspective);
7417 Cvar_RegisterVariable(&r_overheadsprites_pushback);
7420 extern void R_Textures_Init(void);
7421 extern void GL_Draw_Init(void);
7422 extern void GL_Main_Init(void);
7423 extern void R_Shadow_Init(void);
7424 extern void R_Sky_Init(void);
7425 extern void GL_Surf_Init(void);
7426 extern void R_Particles_Init(void);
7427 extern void R_Explosion_Init(void);
7428 extern void gl_backend_init(void);
7429 extern void Sbar_Init(void);
7430 extern void R_LightningBeams_Init(void);
7431 extern void Mod_RenderInit(void);
7432 extern void Font_Init(void);
7434 void Render_Init(void)
7447 R_LightningBeams_Init();
7456 extern char *ENGINE_EXTENSIONS;
7459 gl_renderer = (const char *)qglGetString(GL_RENDERER);
7460 gl_vendor = (const char *)qglGetString(GL_VENDOR);
7461 gl_version = (const char *)qglGetString(GL_VERSION);
7462 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7466 if (!gl_platformextensions)
7467 gl_platformextensions = "";
7469 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7470 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7471 Con_Printf("GL_VERSION: %s\n", gl_version);
7472 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7473 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7475 VID_CheckExtensions();
7477 // LordHavoc: report supported extensions
7478 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7480 // clear to black (loading plaque will be seen over this)
7481 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7484 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7488 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7490 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7493 p = r_refdef.view.frustum + i;
7498 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7502 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7506 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7510 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7514 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7518 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7522 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7526 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7534 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7538 for (i = 0;i < numplanes;i++)
7545 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7549 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7553 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7557 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7561 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7565 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7569 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7573 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7581 //==================================================================================
7583 // LordHavoc: this stores temporary data used within the same frame
7585 qboolean r_framedata_failed;
7586 static size_t r_framedata_size;
7587 static size_t r_framedata_current;
7588 static void *r_framedata_base;
7590 void R_FrameData_Reset(void)
7592 if (r_framedata_base)
7593 Mem_Free(r_framedata_base);
7594 r_framedata_base = NULL;
7595 r_framedata_size = 0;
7596 r_framedata_current = 0;
7597 r_framedata_failed = false;
7600 void R_FrameData_NewFrame(void)
7603 if (r_framedata_failed)
7604 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7605 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7606 wantedsize = bound(65536, wantedsize, 128*1024*1024);
7607 if (r_framedata_size != wantedsize)
7609 r_framedata_size = wantedsize;
7610 if (r_framedata_base)
7611 Mem_Free(r_framedata_base);
7612 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7614 r_framedata_current = 0;
7615 r_framedata_failed = false;
7618 void *R_FrameData_Alloc(size_t size)
7622 // align to 16 byte boundary
7623 size = (size + 15) & ~15;
7624 data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7625 r_framedata_current += size;
7628 if (r_framedata_current > r_framedata_size)
7629 r_framedata_failed = true;
7631 // return NULL on everything after a failure
7632 if (r_framedata_failed)
7638 void *R_FrameData_Store(size_t size, void *data)
7640 void *d = R_FrameData_Alloc(size);
7642 memcpy(d, data, size);
7646 //==================================================================================
7648 // LordHavoc: animcache originally written by Echon, rewritten since then
7651 * Animation cache prevents re-generating mesh data for an animated model
7652 * multiple times in one frame for lighting, shadowing, reflections, etc.
7655 void R_AnimCache_Free(void)
7659 void R_AnimCache_ClearCache(void)
7662 entity_render_t *ent;
7664 for (i = 0;i < r_refdef.scene.numentities;i++)
7666 ent = r_refdef.scene.entities[i];
7667 ent->animcache_vertex3f = NULL;
7668 ent->animcache_normal3f = NULL;
7669 ent->animcache_svector3f = NULL;
7670 ent->animcache_tvector3f = NULL;
7671 ent->animcache_vertexposition = NULL;
7672 ent->animcache_vertexmesh = NULL;
7673 ent->animcache_vertexpositionbuffer = NULL;
7674 ent->animcache_vertexmeshbuffer = NULL;
7678 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7682 // identical memory layout, so no need to allocate...
7683 // this also provides the vertexposition structure to everything, e.g.
7684 // depth masked rendering currently uses it even if having separate
7686 // NOTE: get rid of this optimization if changing it to e.g. 4f
7687 ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7690 // get rid of following uses of VERTEXPOSITION, change to the array:
7691 // R_DrawTextureSurfaceList_Sky if skyrendermasked
7692 // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7693 // R_DrawTextureSurfaceList_DepthOnly
7694 // R_Q1BSP_DrawShadowMap
7696 switch(vid.renderpath)
7698 case RENDERPATH_GL20:
7699 case RENDERPATH_CGGL:
7700 // need the meshbuffers if !gl_mesh_separatearrays.integer
7701 if (gl_mesh_separatearrays.integer)
7704 case RENDERPATH_D3D9:
7705 case RENDERPATH_D3D10:
7706 case RENDERPATH_D3D11:
7707 // always need the meshbuffers
7709 case RENDERPATH_GL13:
7710 case RENDERPATH_GL11:
7711 // never need the meshbuffers
7715 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7716 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7718 if (!ent->animcache_vertexposition)
7719 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7721 if (ent->animcache_vertexposition)
7724 for (i = 0;i < numvertices;i++)
7725 memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7727 // TODO: upload vertex buffer?
7729 if (ent->animcache_vertexmesh)
7731 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7732 for (i = 0;i < numvertices;i++)
7733 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7734 if (ent->animcache_svector3f)
7735 for (i = 0;i < numvertices;i++)
7736 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7737 if (ent->animcache_tvector3f)
7738 for (i = 0;i < numvertices;i++)
7739 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7740 if (ent->animcache_normal3f)
7741 for (i = 0;i < numvertices;i++)
7742 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7743 // TODO: upload vertex buffer?
7747 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7749 dp_model_t *model = ent->model;
7751 // see if it's already cached this frame
7752 if (ent->animcache_vertex3f)
7754 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7755 if (wantnormals || wanttangents)
7757 if (ent->animcache_normal3f)
7758 wantnormals = false;
7759 if (ent->animcache_svector3f)
7760 wanttangents = false;
7761 if (wantnormals || wanttangents)
7763 numvertices = model->surfmesh.num_vertices;
7765 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7768 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7769 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7771 if (!r_framedata_failed)
7773 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7774 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7781 // see if this ent is worth caching
7782 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7784 // get some memory for this entity and generate mesh data
7785 numvertices = model->surfmesh.num_vertices;
7786 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
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, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7797 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7800 return !r_framedata_failed;
7803 void R_AnimCache_CacheVisibleEntities(void)
7806 qboolean wantnormals = true;
7807 qboolean wanttangents = !r_showsurfaces.integer;
7809 switch(vid.renderpath)
7811 case RENDERPATH_GL20:
7812 case RENDERPATH_CGGL:
7813 case RENDERPATH_D3D9:
7814 case RENDERPATH_D3D10:
7815 case RENDERPATH_D3D11:
7817 case RENDERPATH_GL13:
7818 case RENDERPATH_GL11:
7819 wanttangents = false;
7823 if (r_shownormals.integer)
7824 wanttangents = wantnormals = true;
7826 // TODO: thread this
7827 // NOTE: R_PrepareRTLights() also caches entities
7829 for (i = 0;i < r_refdef.scene.numentities;i++)
7830 if (r_refdef.viewcache.entityvisible[i])
7831 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7834 //==================================================================================
7836 static void R_View_UpdateEntityLighting (void)
7839 entity_render_t *ent;
7840 vec3_t tempdiffusenormal, avg;
7841 vec_t f, fa, fd, fdd;
7842 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7844 for (i = 0;i < r_refdef.scene.numentities;i++)
7846 ent = r_refdef.scene.entities[i];
7848 // skip unseen models
7849 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7853 if (ent->model && ent->model->brush.num_leafs)
7855 // TODO: use modellight for r_ambient settings on world?
7856 VectorSet(ent->modellight_ambient, 0, 0, 0);
7857 VectorSet(ent->modellight_diffuse, 0, 0, 0);
7858 VectorSet(ent->modellight_lightdir, 0, 0, 1);
7862 // fetch the lighting from the worldmodel data
7863 VectorClear(ent->modellight_ambient);
7864 VectorClear(ent->modellight_diffuse);
7865 VectorClear(tempdiffusenormal);
7866 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7869 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7871 // complete lightning for lit sprites
7872 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7873 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7875 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7876 org[2] = org[2] + r_overheadsprites_pushback.value;
7877 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7880 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7882 if(ent->flags & RENDER_EQUALIZE)
7884 // first fix up ambient lighting...
7885 if(r_equalize_entities_minambient.value > 0)
7887 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7890 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7891 if(fa < r_equalize_entities_minambient.value * fd)
7894 // fa'/fd' = minambient
7895 // fa'+0.25*fd' = fa+0.25*fd
7897 // fa' = fd' * minambient
7898 // fd'*(0.25+minambient) = fa+0.25*fd
7900 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7901 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7903 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7904 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
7905 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7906 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7911 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7913 VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7914 f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7917 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7918 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7919 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7925 VectorSet(ent->modellight_ambient, 1, 1, 1);
7927 // move the light direction into modelspace coordinates for lighting code
7928 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7929 if(VectorLength2(ent->modellight_lightdir) == 0)
7930 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7931 VectorNormalize(ent->modellight_lightdir);
7935 #define MAX_LINEOFSIGHTTRACES 64
7937 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7940 vec3_t boxmins, boxmaxs;
7943 dp_model_t *model = r_refdef.scene.worldmodel;
7945 if (!model || !model->brush.TraceLineOfSight)
7948 // expand the box a little
7949 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7950 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7951 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7952 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7953 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7954 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7956 // return true if eye is inside enlarged box
7957 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7961 VectorCopy(eye, start);
7962 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7963 if (model->brush.TraceLineOfSight(model, start, end))
7966 // try various random positions
7967 for (i = 0;i < numsamples;i++)
7969 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7970 if (model->brush.TraceLineOfSight(model, start, end))
7978 static void R_View_UpdateEntityVisible (void)
7983 entity_render_t *ent;
7985 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7986 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7987 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
7988 : RENDER_EXTERIORMODEL;
7989 if (!r_drawviewmodel.integer)
7990 renderimask |= RENDER_VIEWMODEL;
7991 if (!r_drawexteriormodel.integer)
7992 renderimask |= RENDER_EXTERIORMODEL;
7993 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7995 // worldmodel can check visibility
7996 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7997 for (i = 0;i < r_refdef.scene.numentities;i++)
7999 ent = r_refdef.scene.entities[i];
8000 if (!(ent->flags & renderimask))
8001 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)))
8002 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))
8003 r_refdef.viewcache.entityvisible[i] = true;
8005 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8006 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8008 for (i = 0;i < r_refdef.scene.numentities;i++)
8010 ent = r_refdef.scene.entities[i];
8011 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8013 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8015 continue; // temp entities do pvs only
8016 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8017 ent->last_trace_visibility = realtime;
8018 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8019 r_refdef.viewcache.entityvisible[i] = 0;
8026 // no worldmodel or it can't check visibility
8027 for (i = 0;i < r_refdef.scene.numentities;i++)
8029 ent = r_refdef.scene.entities[i];
8030 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));
8035 /// only used if skyrendermasked, and normally returns false
8036 int R_DrawBrushModelsSky (void)
8039 entity_render_t *ent;
8042 for (i = 0;i < r_refdef.scene.numentities;i++)
8044 if (!r_refdef.viewcache.entityvisible[i])
8046 ent = r_refdef.scene.entities[i];
8047 if (!ent->model || !ent->model->DrawSky)
8049 ent->model->DrawSky(ent);
8055 static void R_DrawNoModel(entity_render_t *ent);
8056 static void R_DrawModels(void)
8059 entity_render_t *ent;
8061 for (i = 0;i < r_refdef.scene.numentities;i++)
8063 if (!r_refdef.viewcache.entityvisible[i])
8065 ent = r_refdef.scene.entities[i];
8066 r_refdef.stats.entities++;
8067 if (ent->model && ent->model->Draw != NULL)
8068 ent->model->Draw(ent);
8074 static void R_DrawModelsDepth(void)
8077 entity_render_t *ent;
8079 for (i = 0;i < r_refdef.scene.numentities;i++)
8081 if (!r_refdef.viewcache.entityvisible[i])
8083 ent = r_refdef.scene.entities[i];
8084 if (ent->model && ent->model->DrawDepth != NULL)
8085 ent->model->DrawDepth(ent);
8089 static void R_DrawModelsDebug(void)
8092 entity_render_t *ent;
8094 for (i = 0;i < r_refdef.scene.numentities;i++)
8096 if (!r_refdef.viewcache.entityvisible[i])
8098 ent = r_refdef.scene.entities[i];
8099 if (ent->model && ent->model->DrawDebug != NULL)
8100 ent->model->DrawDebug(ent);
8104 static void R_DrawModelsAddWaterPlanes(void)
8107 entity_render_t *ent;
8109 for (i = 0;i < r_refdef.scene.numentities;i++)
8111 if (!r_refdef.viewcache.entityvisible[i])
8113 ent = r_refdef.scene.entities[i];
8114 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8115 ent->model->DrawAddWaterPlanes(ent);
8119 static void R_View_SetFrustum(const int *scissor)
8122 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8123 vec3_t forward, left, up, origin, v;
8127 // flipped x coordinates (because x points left here)
8128 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8129 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8131 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8132 switch(vid.renderpath)
8134 case RENDERPATH_D3D9:
8135 case RENDERPATH_D3D10:
8136 case RENDERPATH_D3D11:
8137 // non-flipped y coordinates
8138 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8139 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8141 case RENDERPATH_GL11:
8142 case RENDERPATH_GL13:
8143 case RENDERPATH_GL20:
8144 case RENDERPATH_CGGL:
8145 // non-flipped y coordinates
8146 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8147 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8152 // we can't trust r_refdef.view.forward and friends in reflected scenes
8153 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8156 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8157 r_refdef.view.frustum[0].normal[1] = 0 - 0;
8158 r_refdef.view.frustum[0].normal[2] = -1 - 0;
8159 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8160 r_refdef.view.frustum[1].normal[1] = 0 + 0;
8161 r_refdef.view.frustum[1].normal[2] = -1 + 0;
8162 r_refdef.view.frustum[2].normal[0] = 0 - 0;
8163 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8164 r_refdef.view.frustum[2].normal[2] = -1 - 0;
8165 r_refdef.view.frustum[3].normal[0] = 0 + 0;
8166 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8167 r_refdef.view.frustum[3].normal[2] = -1 + 0;
8171 zNear = r_refdef.nearclip;
8172 nudge = 1.0 - 1.0 / (1<<23);
8173 r_refdef.view.frustum[4].normal[0] = 0 - 0;
8174 r_refdef.view.frustum[4].normal[1] = 0 - 0;
8175 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8176 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8177 r_refdef.view.frustum[5].normal[0] = 0 + 0;
8178 r_refdef.view.frustum[5].normal[1] = 0 + 0;
8179 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8180 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8186 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8187 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8188 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8189 r_refdef.view.frustum[0].dist = m[15] - m[12];
8191 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8192 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8193 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8194 r_refdef.view.frustum[1].dist = m[15] + m[12];
8196 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8197 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8198 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8199 r_refdef.view.frustum[2].dist = m[15] - m[13];
8201 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8202 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8203 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8204 r_refdef.view.frustum[3].dist = m[15] + m[13];
8206 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8207 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8208 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8209 r_refdef.view.frustum[4].dist = m[15] - m[14];
8211 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8212 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8213 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8214 r_refdef.view.frustum[5].dist = m[15] + m[14];
8217 if (r_refdef.view.useperspective)
8219 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8220 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]);
8221 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]);
8222 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]);
8223 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]);
8225 // then the normals from the corners relative to origin
8226 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8227 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8228 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8229 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8231 // in a NORMAL view, forward cross left == up
8232 // in a REFLECTED view, forward cross left == down
8233 // so our cross products above need to be adjusted for a left handed coordinate system
8234 CrossProduct(forward, left, v);
8235 if(DotProduct(v, up) < 0)
8237 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8238 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8239 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8240 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8243 // Leaving those out was a mistake, those were in the old code, and they
8244 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8245 // I couldn't reproduce it after adding those normalizations. --blub
8246 VectorNormalize(r_refdef.view.frustum[0].normal);
8247 VectorNormalize(r_refdef.view.frustum[1].normal);
8248 VectorNormalize(r_refdef.view.frustum[2].normal);
8249 VectorNormalize(r_refdef.view.frustum[3].normal);
8251 // make the corners absolute
8252 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8253 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8254 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8255 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8258 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8260 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8261 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8262 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8263 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8264 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8268 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8269 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8270 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8271 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8272 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8273 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8274 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8275 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8276 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8277 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8279 r_refdef.view.numfrustumplanes = 5;
8281 if (r_refdef.view.useclipplane)
8283 r_refdef.view.numfrustumplanes = 6;
8284 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8287 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8288 PlaneClassify(r_refdef.view.frustum + i);
8290 // LordHavoc: note to all quake engine coders, Quake had a special case
8291 // for 90 degrees which assumed a square view (wrong), so I removed it,
8292 // Quake2 has it disabled as well.
8294 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8295 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8296 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8297 //PlaneClassify(&frustum[0]);
8299 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8300 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8301 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8302 //PlaneClassify(&frustum[1]);
8304 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8305 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8306 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8307 //PlaneClassify(&frustum[2]);
8309 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8310 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8311 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8312 //PlaneClassify(&frustum[3]);
8315 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8316 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8317 //PlaneClassify(&frustum[4]);
8320 void R_View_UpdateWithScissor(const int *myscissor)
8322 R_Main_ResizeViewCache();
8323 R_View_SetFrustum(myscissor);
8324 R_View_WorldVisibility(r_refdef.view.useclipplane);
8325 R_View_UpdateEntityVisible();
8326 R_View_UpdateEntityLighting();
8329 void R_View_Update(void)
8331 R_Main_ResizeViewCache();
8332 R_View_SetFrustum(NULL);
8333 R_View_WorldVisibility(r_refdef.view.useclipplane);
8334 R_View_UpdateEntityVisible();
8335 R_View_UpdateEntityLighting();
8338 void R_SetupView(qboolean allowwaterclippingplane)
8340 const float *customclipplane = NULL;
8342 if (r_refdef.view.useclipplane && allowwaterclippingplane)
8344 // LordHavoc: couldn't figure out how to make this approach the
8345 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8346 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8347 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8348 dist = r_refdef.view.clipplane.dist;
8349 plane[0] = r_refdef.view.clipplane.normal[0];
8350 plane[1] = r_refdef.view.clipplane.normal[1];
8351 plane[2] = r_refdef.view.clipplane.normal[2];
8353 customclipplane = plane;
8356 if (!r_refdef.view.useperspective)
8357 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);
8358 else if (vid.stencil && r_useinfinitefarclip.integer)
8359 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);
8361 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);
8362 R_SetViewport(&r_refdef.view.viewport);
8365 void R_EntityMatrix(const matrix4x4_t *matrix)
8367 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8369 gl_modelmatrixchanged = false;
8370 gl_modelmatrix = *matrix;
8371 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8372 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8373 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8374 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8376 switch(vid.renderpath)
8378 case RENDERPATH_D3D9:
8380 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8381 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8384 case RENDERPATH_D3D10:
8385 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8387 case RENDERPATH_D3D11:
8388 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8390 case RENDERPATH_GL20:
8391 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8392 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8393 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8395 case RENDERPATH_CGGL:
8398 if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8399 if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8400 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8403 case RENDERPATH_GL13:
8404 case RENDERPATH_GL11:
8405 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8411 void R_ResetViewRendering2D(void)
8413 r_viewport_t viewport;
8416 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8417 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);
8418 R_SetViewport(&viewport);
8419 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8420 GL_Color(1, 1, 1, 1);
8421 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8422 GL_BlendFunc(GL_ONE, GL_ZERO);
8423 GL_AlphaTest(false);
8424 GL_ScissorTest(false);
8425 GL_DepthMask(false);
8426 GL_DepthRange(0, 1);
8427 GL_DepthTest(false);
8428 GL_DepthFunc(GL_LEQUAL);
8429 R_EntityMatrix(&identitymatrix);
8430 R_Mesh_ResetTextureState();
8431 GL_PolygonOffset(0, 0);
8432 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8433 switch(vid.renderpath)
8435 case RENDERPATH_GL11:
8436 case RENDERPATH_GL13:
8437 case RENDERPATH_GL20:
8438 case RENDERPATH_CGGL:
8439 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8441 case RENDERPATH_D3D9:
8442 case RENDERPATH_D3D10:
8443 case RENDERPATH_D3D11:
8446 GL_CullFace(GL_NONE);
8449 void R_ResetViewRendering3D(void)
8454 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8455 GL_Color(1, 1, 1, 1);
8456 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8457 GL_BlendFunc(GL_ONE, GL_ZERO);
8458 GL_AlphaTest(false);
8459 GL_ScissorTest(true);
8461 GL_DepthRange(0, 1);
8463 GL_DepthFunc(GL_LEQUAL);
8464 R_EntityMatrix(&identitymatrix);
8465 R_Mesh_ResetTextureState();
8466 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8467 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8468 switch(vid.renderpath)
8470 case RENDERPATH_GL11:
8471 case RENDERPATH_GL13:
8472 case RENDERPATH_GL20:
8473 case RENDERPATH_CGGL:
8474 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8476 case RENDERPATH_D3D9:
8477 case RENDERPATH_D3D10:
8478 case RENDERPATH_D3D11:
8481 GL_CullFace(r_refdef.view.cullface_back);
8486 R_RenderView_UpdateViewVectors
8489 static void R_RenderView_UpdateViewVectors(void)
8491 // break apart the view matrix into vectors for various purposes
8492 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8493 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8494 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8495 VectorNegate(r_refdef.view.left, r_refdef.view.right);
8496 // make an inverted copy of the view matrix for tracking sprites
8497 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8500 void R_RenderScene(void);
8501 void R_RenderWaterPlanes(void);
8503 static void R_Water_StartFrame(void)
8506 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8507 r_waterstate_waterplane_t *p;
8509 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8512 switch(vid.renderpath)
8514 case RENDERPATH_GL20:
8515 case RENDERPATH_CGGL:
8516 case RENDERPATH_D3D9:
8517 case RENDERPATH_D3D10:
8518 case RENDERPATH_D3D11:
8520 case RENDERPATH_GL13:
8521 case RENDERPATH_GL11:
8525 // set waterwidth and waterheight to the water resolution that will be
8526 // used (often less than the screen resolution for faster rendering)
8527 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8528 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8530 // calculate desired texture sizes
8531 // can't use water if the card does not support the texture size
8532 if (!r_water.integer || r_showsurfaces.integer)
8533 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8534 else if (vid.support.arb_texture_non_power_of_two)
8536 texturewidth = waterwidth;
8537 textureheight = waterheight;
8538 camerawidth = waterwidth;
8539 cameraheight = waterheight;
8543 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
8544 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
8545 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
8546 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
8549 // allocate textures as needed
8550 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8552 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8553 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8555 if (p->texture_refraction)
8556 R_FreeTexture(p->texture_refraction);
8557 p->texture_refraction = NULL;
8558 if (p->texture_reflection)
8559 R_FreeTexture(p->texture_reflection);
8560 p->texture_reflection = NULL;
8561 if (p->texture_camera)
8562 R_FreeTexture(p->texture_camera);
8563 p->texture_camera = NULL;
8565 memset(&r_waterstate, 0, sizeof(r_waterstate));
8566 r_waterstate.texturewidth = texturewidth;
8567 r_waterstate.textureheight = textureheight;
8568 r_waterstate.camerawidth = camerawidth;
8569 r_waterstate.cameraheight = cameraheight;
8572 if (r_waterstate.texturewidth)
8574 r_waterstate.enabled = true;
8576 // when doing a reduced render (HDR) we want to use a smaller area
8577 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8578 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8580 // set up variables that will be used in shader setup
8581 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8582 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8583 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8584 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8587 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8588 r_waterstate.numwaterplanes = 0;
8591 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8593 int triangleindex, planeindex;
8599 r_waterstate_waterplane_t *p;
8600 texture_t *t = R_GetCurrentTexture(surface->texture);
8602 // just use the first triangle with a valid normal for any decisions
8603 VectorClear(normal);
8604 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8606 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8607 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8608 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8609 TriangleNormal(vert[0], vert[1], vert[2], normal);
8610 if (VectorLength2(normal) >= 0.001)
8614 VectorCopy(normal, plane.normal);
8615 VectorNormalize(plane.normal);
8616 plane.dist = DotProduct(vert[0], plane.normal);
8617 PlaneClassify(&plane);
8618 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8620 // skip backfaces (except if nocullface is set)
8621 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8623 VectorNegate(plane.normal, plane.normal);
8625 PlaneClassify(&plane);
8629 // find a matching plane if there is one
8630 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8631 if(p->camera_entity == t->camera_entity)
8632 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8634 if (planeindex >= r_waterstate.maxwaterplanes)
8635 return; // nothing we can do, out of planes
8637 // if this triangle does not fit any known plane rendered this frame, add one
8638 if (planeindex >= r_waterstate.numwaterplanes)
8640 // store the new plane
8641 r_waterstate.numwaterplanes++;
8643 // clear materialflags and pvs
8644 p->materialflags = 0;
8645 p->pvsvalid = false;
8646 p->camera_entity = t->camera_entity;
8647 VectorCopy(surface->mins, p->mins);
8648 VectorCopy(surface->maxs, p->maxs);
8653 p->mins[0] = min(p->mins[0], surface->mins[0]);
8654 p->mins[1] = min(p->mins[1], surface->mins[1]);
8655 p->mins[2] = min(p->mins[2], surface->mins[2]);
8656 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8657 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8658 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8660 // merge this surface's materialflags into the waterplane
8661 p->materialflags |= t->currentmaterialflags;
8662 if(!(p->materialflags & MATERIALFLAG_CAMERA))
8664 // merge this surface's PVS into the waterplane
8665 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8666 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8667 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8669 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8675 static void R_Water_ProcessPlanes(void)
8678 r_refdef_view_t originalview;
8679 r_refdef_view_t myview;
8681 r_waterstate_waterplane_t *p;
8684 originalview = r_refdef.view;
8686 // make sure enough textures are allocated
8687 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8689 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8691 if (!p->texture_refraction)
8692 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);
8693 if (!p->texture_refraction)
8696 else if (p->materialflags & MATERIALFLAG_CAMERA)
8698 if (!p->texture_camera)
8699 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);
8700 if (!p->texture_camera)
8704 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8706 if (!p->texture_reflection)
8707 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);
8708 if (!p->texture_reflection)
8714 r_refdef.view = originalview;
8715 r_refdef.view.showdebug = false;
8716 r_refdef.view.width = r_waterstate.waterwidth;
8717 r_refdef.view.height = r_waterstate.waterheight;
8718 r_refdef.view.useclipplane = true;
8719 myview = r_refdef.view;
8720 r_waterstate.renderingscene = true;
8721 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8723 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8725 r_refdef.view = myview;
8726 if(r_water_scissormode.integer)
8729 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8730 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8733 // render reflected scene and copy into texture
8734 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8735 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8736 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8737 r_refdef.view.clipplane = p->plane;
8739 // reverse the cullface settings for this render
8740 r_refdef.view.cullface_front = GL_FRONT;
8741 r_refdef.view.cullface_back = GL_BACK;
8742 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8744 r_refdef.view.usecustompvs = true;
8746 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8748 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8751 R_ResetViewRendering3D();
8752 R_ClearScreen(r_refdef.fogenabled);
8753 if(r_water_scissormode.integer & 2)
8754 R_View_UpdateWithScissor(myscissor);
8757 if(r_water_scissormode.integer & 1)
8758 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8761 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);
8764 // render the normal view scene and copy into texture
8765 // (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)
8766 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8768 r_refdef.view = myview;
8769 if(r_water_scissormode.integer)
8772 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8773 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8776 r_waterstate.renderingrefraction = true;
8778 r_refdef.view.clipplane = p->plane;
8779 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8780 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8782 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8784 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8785 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8786 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8787 R_RenderView_UpdateViewVectors();
8788 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8790 r_refdef.view.usecustompvs = true;
8791 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);
8795 PlaneClassify(&r_refdef.view.clipplane);
8797 R_ResetViewRendering3D();
8798 R_ClearScreen(r_refdef.fogenabled);
8799 if(r_water_scissormode.integer & 2)
8800 R_View_UpdateWithScissor(myscissor);
8803 if(r_water_scissormode.integer & 1)
8804 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8807 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);
8808 r_waterstate.renderingrefraction = false;
8810 else if (p->materialflags & MATERIALFLAG_CAMERA)
8812 r_refdef.view = myview;
8814 r_refdef.view.clipplane = p->plane;
8815 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8816 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8818 r_refdef.view.width = r_waterstate.camerawidth;
8819 r_refdef.view.height = r_waterstate.cameraheight;
8820 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8821 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8823 if(p->camera_entity)
8825 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8826 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8829 // note: all of the view is used for displaying... so
8830 // there is no use in scissoring
8832 // reverse the cullface settings for this render
8833 r_refdef.view.cullface_front = GL_FRONT;
8834 r_refdef.view.cullface_back = GL_BACK;
8835 // also reverse the view matrix
8836 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
8837 R_RenderView_UpdateViewVectors();
8838 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8840 r_refdef.view.usecustompvs = true;
8841 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);
8844 // camera needs no clipplane
8845 r_refdef.view.useclipplane = false;
8847 PlaneClassify(&r_refdef.view.clipplane);
8849 R_ResetViewRendering3D();
8850 R_ClearScreen(r_refdef.fogenabled);
8854 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);
8855 r_waterstate.renderingrefraction = false;
8859 r_waterstate.renderingscene = false;
8860 r_refdef.view = originalview;
8861 R_ResetViewRendering3D();
8862 R_ClearScreen(r_refdef.fogenabled);
8866 r_refdef.view = originalview;
8867 r_waterstate.renderingscene = false;
8868 Cvar_SetValueQuick(&r_water, 0);
8869 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
8873 void R_Bloom_StartFrame(void)
8875 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8877 switch(vid.renderpath)
8879 case RENDERPATH_GL20:
8880 case RENDERPATH_CGGL:
8881 case RENDERPATH_D3D9:
8882 case RENDERPATH_D3D10:
8883 case RENDERPATH_D3D11:
8885 case RENDERPATH_GL13:
8886 case RENDERPATH_GL11:
8890 // set bloomwidth and bloomheight to the bloom resolution that will be
8891 // used (often less than the screen resolution for faster rendering)
8892 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8893 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8894 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8895 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8896 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8898 // calculate desired texture sizes
8899 if (vid.support.arb_texture_non_power_of_two)
8901 screentexturewidth = r_refdef.view.width;
8902 screentextureheight = r_refdef.view.height;
8903 bloomtexturewidth = r_bloomstate.bloomwidth;
8904 bloomtextureheight = r_bloomstate.bloomheight;
8908 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
8909 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
8910 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
8911 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
8914 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))
8916 Cvar_SetValueQuick(&r_hdr, 0);
8917 Cvar_SetValueQuick(&r_bloom, 0);
8918 Cvar_SetValueQuick(&r_motionblur, 0);
8919 Cvar_SetValueQuick(&r_damageblur, 0);
8922 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)))
8923 screentexturewidth = screentextureheight = 0;
8924 if (!r_hdr.integer && !r_bloom.integer)
8925 bloomtexturewidth = bloomtextureheight = 0;
8927 // allocate textures as needed
8928 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8930 if (r_bloomstate.texture_screen)
8931 R_FreeTexture(r_bloomstate.texture_screen);
8932 r_bloomstate.texture_screen = NULL;
8933 r_bloomstate.screentexturewidth = screentexturewidth;
8934 r_bloomstate.screentextureheight = screentextureheight;
8935 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8936 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);
8938 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8940 if (r_bloomstate.texture_bloom)
8941 R_FreeTexture(r_bloomstate.texture_bloom);
8942 r_bloomstate.texture_bloom = NULL;
8943 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8944 r_bloomstate.bloomtextureheight = bloomtextureheight;
8945 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8946 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);
8949 // when doing a reduced render (HDR) we want to use a smaller area
8950 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8951 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8952 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8953 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8954 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8956 // set up a texcoord array for the full resolution screen image
8957 // (we have to keep this around to copy back during final render)
8958 r_bloomstate.screentexcoord2f[0] = 0;
8959 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8960 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8961 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
8962 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
8963 r_bloomstate.screentexcoord2f[5] = 0;
8964 r_bloomstate.screentexcoord2f[6] = 0;
8965 r_bloomstate.screentexcoord2f[7] = 0;
8967 // set up a texcoord array for the reduced resolution bloom image
8968 // (which will be additive blended over the screen image)
8969 r_bloomstate.bloomtexcoord2f[0] = 0;
8970 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8971 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8972 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8973 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8974 r_bloomstate.bloomtexcoord2f[5] = 0;
8975 r_bloomstate.bloomtexcoord2f[6] = 0;
8976 r_bloomstate.bloomtexcoord2f[7] = 0;
8978 switch(vid.renderpath)
8980 case RENDERPATH_GL11:
8981 case RENDERPATH_GL13:
8982 case RENDERPATH_GL20:
8983 case RENDERPATH_CGGL:
8985 case RENDERPATH_D3D9:
8986 case RENDERPATH_D3D10:
8987 case RENDERPATH_D3D11:
8990 for (i = 0;i < 4;i++)
8992 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8993 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8994 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8995 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9001 if (r_hdr.integer || r_bloom.integer)
9003 r_bloomstate.enabled = true;
9004 r_bloomstate.hdr = r_hdr.integer != 0;
9007 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);
9010 void R_Bloom_CopyBloomTexture(float colorscale)
9012 r_refdef.stats.bloom++;
9014 // scale down screen texture to the bloom texture size
9016 R_SetViewport(&r_bloomstate.viewport);
9017 GL_BlendFunc(GL_ONE, GL_ZERO);
9018 GL_Color(colorscale, colorscale, colorscale, 1);
9019 // 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...
9020 switch(vid.renderpath)
9022 case RENDERPATH_GL11:
9023 case RENDERPATH_GL13:
9024 case RENDERPATH_GL20:
9025 case RENDERPATH_CGGL:
9026 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9028 case RENDERPATH_D3D9:
9029 case RENDERPATH_D3D10:
9030 case RENDERPATH_D3D11:
9031 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9034 // TODO: do boxfilter scale-down in shader?
9035 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9036 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9037 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9039 // we now have a bloom image in the framebuffer
9040 // copy it into the bloom image texture for later processing
9041 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);
9042 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9045 void R_Bloom_CopyHDRTexture(void)
9047 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);
9048 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9051 void R_Bloom_MakeTexture(void)
9054 float xoffset, yoffset, r, brighten;
9056 r_refdef.stats.bloom++;
9058 R_ResetViewRendering2D();
9060 // we have a bloom image in the framebuffer
9062 R_SetViewport(&r_bloomstate.viewport);
9064 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9067 r = bound(0, r_bloom_colorexponent.value / x, 1);
9068 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9070 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9071 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9072 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9073 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9075 // copy the vertically blurred bloom view to a texture
9076 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);
9077 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9080 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9081 brighten = r_bloom_brighten.value;
9083 brighten *= r_hdr_range.value;
9084 brighten = sqrt(brighten);
9086 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9087 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9089 for (dir = 0;dir < 2;dir++)
9091 // blend on at multiple vertical offsets to achieve a vertical blur
9092 // TODO: do offset blends using GLSL
9093 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9094 GL_BlendFunc(GL_ONE, GL_ZERO);
9095 for (x = -range;x <= range;x++)
9097 if (!dir){xoffset = 0;yoffset = x;}
9098 else {xoffset = x;yoffset = 0;}
9099 xoffset /= (float)r_bloomstate.bloomtexturewidth;
9100 yoffset /= (float)r_bloomstate.bloomtextureheight;
9101 // compute a texcoord array with the specified x and y offset
9102 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9103 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9104 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9105 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9106 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9107 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9108 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9109 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9110 // this r value looks like a 'dot' particle, fading sharply to
9111 // black at the edges
9112 // (probably not realistic but looks good enough)
9113 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9114 //r = brighten/(range*2+1);
9115 r = brighten / (range * 2 + 1);
9117 r *= (1 - x*x/(float)(range*range));
9118 GL_Color(r, r, r, 1);
9119 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9120 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9121 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9122 GL_BlendFunc(GL_ONE, GL_ONE);
9125 // copy the vertically blurred bloom view to a texture
9126 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);
9127 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9131 void R_HDR_RenderBloomTexture(void)
9133 int oldwidth, oldheight;
9134 float oldcolorscale;
9136 oldcolorscale = r_refdef.view.colorscale;
9137 oldwidth = r_refdef.view.width;
9138 oldheight = r_refdef.view.height;
9139 r_refdef.view.width = r_bloomstate.bloomwidth;
9140 r_refdef.view.height = r_bloomstate.bloomheight;
9142 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
9143 // TODO: add exposure compensation features
9144 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9146 r_refdef.view.showdebug = false;
9147 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9149 R_ResetViewRendering3D();
9151 R_ClearScreen(r_refdef.fogenabled);
9152 if (r_timereport_active)
9153 R_TimeReport("HDRclear");
9156 if (r_timereport_active)
9157 R_TimeReport("visibility");
9159 // only do secondary renders with HDR if r_hdr is 2 or higher
9160 r_waterstate.numwaterplanes = 0;
9161 if (r_waterstate.enabled && r_hdr.integer >= 2)
9162 R_RenderWaterPlanes();
9164 r_refdef.view.showdebug = true;
9166 r_waterstate.numwaterplanes = 0;
9168 R_ResetViewRendering2D();
9170 R_Bloom_CopyHDRTexture();
9171 R_Bloom_MakeTexture();
9173 // restore the view settings
9174 r_refdef.view.width = oldwidth;
9175 r_refdef.view.height = oldheight;
9176 r_refdef.view.colorscale = oldcolorscale;
9178 R_ResetViewRendering3D();
9180 R_ClearScreen(r_refdef.fogenabled);
9181 if (r_timereport_active)
9182 R_TimeReport("viewclear");
9185 static void R_BlendView(void)
9187 unsigned int permutation;
9188 float uservecs[4][4];
9190 switch (vid.renderpath)
9192 case RENDERPATH_GL20:
9193 case RENDERPATH_CGGL:
9194 case RENDERPATH_D3D9:
9195 case RENDERPATH_D3D10:
9196 case RENDERPATH_D3D11:
9198 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9199 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9200 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9201 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9202 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9204 if (r_bloomstate.texture_screen)
9206 // make sure the buffer is available
9207 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9209 R_ResetViewRendering2D();
9211 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9213 // declare variables
9215 static float avgspeed;
9217 speed = VectorLength(cl.movement_velocity);
9219 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9220 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9222 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9223 speed = bound(0, speed, 1);
9224 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9226 // calculate values into a standard alpha
9227 cl.motionbluralpha = 1 - exp(-
9229 (r_motionblur.value * speed / 80)
9231 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9234 max(0.0001, cl.time - cl.oldtime) // fps independent
9237 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9238 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9240 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9242 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9243 GL_Color(1, 1, 1, cl.motionbluralpha);
9244 switch(vid.renderpath)
9246 case RENDERPATH_GL11:
9247 case RENDERPATH_GL13:
9248 case RENDERPATH_GL20:
9249 case RENDERPATH_CGGL:
9250 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9252 case RENDERPATH_D3D9:
9253 case RENDERPATH_D3D10:
9254 case RENDERPATH_D3D11:
9255 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9258 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9259 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9260 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9264 // copy view into the screen texture
9265 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);
9266 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9268 else if (!r_bloomstate.texture_bloom)
9270 // we may still have to do view tint...
9271 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9273 // apply a color tint to the whole view
9274 R_ResetViewRendering2D();
9275 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9276 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9277 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9278 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9279 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9281 break; // no screen processing, no bloom, skip it
9284 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9286 // render simple bloom effect
9287 // copy the screen and shrink it and darken it for the bloom process
9288 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9289 // make the bloom texture
9290 R_Bloom_MakeTexture();
9293 #if _MSC_VER >= 1400
9294 #define sscanf sscanf_s
9296 memset(uservecs, 0, sizeof(uservecs));
9297 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9298 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9299 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9300 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9302 R_ResetViewRendering2D();
9303 GL_Color(1, 1, 1, 1);
9304 GL_BlendFunc(GL_ONE, GL_ZERO);
9306 switch(vid.renderpath)
9308 case RENDERPATH_GL20:
9309 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9310 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9311 if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9312 if (r_glsl_permutation->loc_Texture_Second >= 0) R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9313 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9314 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]);
9315 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9316 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]);
9317 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]);
9318 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]);
9319 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]);
9320 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
9321 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9322 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);
9324 case RENDERPATH_CGGL:
9326 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9327 R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9328 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , r_bloomstate.texture_screen);CHECKCGERROR
9329 if (r_cg_permutation->fp_Texture_Second ) CG_BindTexture(r_cg_permutation->fp_Texture_Second , r_bloomstate.texture_bloom );CHECKCGERROR
9330 if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps );CHECKCGERROR
9331 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
9332 if (r_cg_permutation->fp_PixelSize ) cgGLSetParameter2f( r_cg_permutation->fp_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9333 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
9334 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
9335 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
9336 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
9337 if (r_cg_permutation->fp_Saturation ) cgGLSetParameter1f( r_cg_permutation->fp_Saturation , r_glsl_saturation.value);CHECKCGERROR
9338 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9339 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);
9342 case RENDERPATH_D3D9:
9344 // 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...
9345 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9346 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9347 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
9348 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
9349 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
9350 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9351 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9352 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9353 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9354 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9355 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9356 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
9357 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9358 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9361 case RENDERPATH_D3D10:
9362 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9364 case RENDERPATH_D3D11:
9365 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9370 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9371 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9373 case RENDERPATH_GL13:
9374 case RENDERPATH_GL11:
9375 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9377 // apply a color tint to the whole view
9378 R_ResetViewRendering2D();
9379 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9380 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9381 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9382 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9383 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9389 matrix4x4_t r_waterscrollmatrix;
9391 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9393 if (r_refdef.fog_density)
9395 r_refdef.fogcolor[0] = r_refdef.fog_red;
9396 r_refdef.fogcolor[1] = r_refdef.fog_green;
9397 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9399 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9400 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9401 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9402 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9406 VectorCopy(r_refdef.fogcolor, fogvec);
9407 // color.rgb *= ContrastBoost * SceneBrightness;
9408 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9409 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9410 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9411 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9416 void R_UpdateVariables(void)
9420 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9422 r_refdef.farclip = r_farclip_base.value;
9423 if (r_refdef.scene.worldmodel)
9424 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9425 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9427 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9428 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9429 r_refdef.polygonfactor = 0;
9430 r_refdef.polygonoffset = 0;
9431 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9432 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9434 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9435 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9436 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9437 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9438 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9439 if (FAKELIGHT_ENABLED)
9441 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9443 if (r_showsurfaces.integer)
9445 r_refdef.scene.rtworld = false;
9446 r_refdef.scene.rtworldshadows = false;
9447 r_refdef.scene.rtdlight = false;
9448 r_refdef.scene.rtdlightshadows = false;
9449 r_refdef.lightmapintensity = 0;
9452 if (gamemode == GAME_NEHAHRA)
9454 if (gl_fogenable.integer)
9456 r_refdef.oldgl_fogenable = true;
9457 r_refdef.fog_density = gl_fogdensity.value;
9458 r_refdef.fog_red = gl_fogred.value;
9459 r_refdef.fog_green = gl_foggreen.value;
9460 r_refdef.fog_blue = gl_fogblue.value;
9461 r_refdef.fog_alpha = 1;
9462 r_refdef.fog_start = 0;
9463 r_refdef.fog_end = gl_skyclip.value;
9464 r_refdef.fog_height = 1<<30;
9465 r_refdef.fog_fadedepth = 128;
9467 else if (r_refdef.oldgl_fogenable)
9469 r_refdef.oldgl_fogenable = false;
9470 r_refdef.fog_density = 0;
9471 r_refdef.fog_red = 0;
9472 r_refdef.fog_green = 0;
9473 r_refdef.fog_blue = 0;
9474 r_refdef.fog_alpha = 0;
9475 r_refdef.fog_start = 0;
9476 r_refdef.fog_end = 0;
9477 r_refdef.fog_height = 1<<30;
9478 r_refdef.fog_fadedepth = 128;
9482 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9483 r_refdef.fog_start = max(0, r_refdef.fog_start);
9484 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9486 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9488 if (r_refdef.fog_density && r_drawfog.integer)
9490 r_refdef.fogenabled = true;
9491 // this is the point where the fog reaches 0.9986 alpha, which we
9492 // consider a good enough cutoff point for the texture
9493 // (0.9986 * 256 == 255.6)
9494 if (r_fog_exp2.integer)
9495 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9497 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9498 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9499 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9500 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9501 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9502 R_BuildFogHeightTexture();
9503 // fog color was already set
9504 // update the fog texture
9505 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)
9506 R_BuildFogTexture();
9507 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9508 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9511 r_refdef.fogenabled = false;
9513 switch(vid.renderpath)
9515 case RENDERPATH_GL20:
9516 case RENDERPATH_CGGL:
9517 case RENDERPATH_D3D9:
9518 case RENDERPATH_D3D10:
9519 case RENDERPATH_D3D11:
9520 if(v_glslgamma.integer && !vid_gammatables_trivial)
9522 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9524 // build GLSL gamma texture
9525 #define RAMPWIDTH 256
9526 unsigned short ramp[RAMPWIDTH * 3];
9527 unsigned char rampbgr[RAMPWIDTH][4];
9530 r_texture_gammaramps_serial = vid_gammatables_serial;
9532 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9533 for(i = 0; i < RAMPWIDTH; ++i)
9535 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9536 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9537 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9540 if (r_texture_gammaramps)
9542 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9546 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9552 // remove GLSL gamma texture
9555 case RENDERPATH_GL13:
9556 case RENDERPATH_GL11:
9561 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9562 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9568 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9569 if( scenetype != r_currentscenetype ) {
9570 // store the old scenetype
9571 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9572 r_currentscenetype = scenetype;
9573 // move in the new scene
9574 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9583 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9585 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9586 if( scenetype == r_currentscenetype ) {
9587 return &r_refdef.scene;
9589 return &r_scenes_store[ scenetype ];
9598 void R_RenderView(void)
9600 if (r_timereport_active)
9601 R_TimeReport("start");
9602 r_textureframe++; // used only by R_GetCurrentTexture
9603 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9605 if(R_CompileShader_CheckStaticParms())
9608 if (!r_drawentities.integer)
9609 r_refdef.scene.numentities = 0;
9611 R_AnimCache_ClearCache();
9612 R_FrameData_NewFrame();
9614 if (r_refdef.view.isoverlay)
9616 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9617 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9618 R_TimeReport("depthclear");
9620 r_refdef.view.showdebug = false;
9622 r_waterstate.enabled = false;
9623 r_waterstate.numwaterplanes = 0;
9631 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9632 return; //Host_Error ("R_RenderView: NULL worldmodel");
9634 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9636 R_RenderView_UpdateViewVectors();
9638 R_Shadow_UpdateWorldLightSelection();
9640 R_Bloom_StartFrame();
9641 R_Water_StartFrame();
9644 if (r_timereport_active)
9645 R_TimeReport("viewsetup");
9647 R_ResetViewRendering3D();
9649 if (r_refdef.view.clear || r_refdef.fogenabled)
9651 R_ClearScreen(r_refdef.fogenabled);
9652 if (r_timereport_active)
9653 R_TimeReport("viewclear");
9655 r_refdef.view.clear = true;
9657 // this produces a bloom texture to be used in R_BlendView() later
9658 if (r_hdr.integer && r_bloomstate.bloomwidth)
9660 R_HDR_RenderBloomTexture();
9661 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9662 r_textureframe++; // used only by R_GetCurrentTexture
9665 r_refdef.view.showdebug = true;
9668 if (r_timereport_active)
9669 R_TimeReport("visibility");
9671 r_waterstate.numwaterplanes = 0;
9672 if (r_waterstate.enabled)
9673 R_RenderWaterPlanes();
9676 r_waterstate.numwaterplanes = 0;
9679 if (r_timereport_active)
9680 R_TimeReport("blendview");
9682 GL_Scissor(0, 0, vid.width, vid.height);
9683 GL_ScissorTest(false);
9688 void R_RenderWaterPlanes(void)
9690 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9692 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9693 if (r_timereport_active)
9694 R_TimeReport("waterworld");
9697 // don't let sound skip if going slow
9698 if (r_refdef.scene.extraupdate)
9701 R_DrawModelsAddWaterPlanes();
9702 if (r_timereport_active)
9703 R_TimeReport("watermodels");
9705 if (r_waterstate.numwaterplanes)
9707 R_Water_ProcessPlanes();
9708 if (r_timereport_active)
9709 R_TimeReport("waterscenes");
9713 extern void R_DrawLightningBeams (void);
9714 extern void VM_CL_AddPolygonsToMeshQueue (void);
9715 extern void R_DrawPortals (void);
9716 extern cvar_t cl_locs_show;
9717 static void R_DrawLocs(void);
9718 static void R_DrawEntityBBoxes(void);
9719 static void R_DrawModelDecals(void);
9720 extern void R_DrawModelShadows(void);
9721 extern void R_DrawModelShadowMaps(void);
9722 extern cvar_t cl_decals_newsystem;
9723 extern qboolean r_shadow_usingdeferredprepass;
9724 void R_RenderScene(void)
9726 qboolean shadowmapping = false;
9728 if (r_timereport_active)
9729 R_TimeReport("beginscene");
9731 r_refdef.stats.renders++;
9735 // don't let sound skip if going slow
9736 if (r_refdef.scene.extraupdate)
9739 R_MeshQueue_BeginScene();
9743 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);
9745 if (r_timereport_active)
9746 R_TimeReport("skystartframe");
9748 if (cl.csqc_vidvars.drawworld)
9750 // don't let sound skip if going slow
9751 if (r_refdef.scene.extraupdate)
9754 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9756 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9757 if (r_timereport_active)
9758 R_TimeReport("worldsky");
9761 if (R_DrawBrushModelsSky() && r_timereport_active)
9762 R_TimeReport("bmodelsky");
9764 if (skyrendermasked && skyrenderlater)
9766 // we have to force off the water clipping plane while rendering sky
9770 if (r_timereport_active)
9771 R_TimeReport("sky");
9775 R_AnimCache_CacheVisibleEntities();
9776 if (r_timereport_active)
9777 R_TimeReport("animation");
9779 R_Shadow_PrepareLights();
9780 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9781 R_Shadow_PrepareModelShadows();
9782 if (r_timereport_active)
9783 R_TimeReport("preparelights");
9785 if (R_Shadow_ShadowMappingEnabled())
9786 shadowmapping = true;
9788 if (r_shadow_usingdeferredprepass)
9789 R_Shadow_DrawPrepass();
9791 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9793 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9794 if (r_timereport_active)
9795 R_TimeReport("worlddepth");
9797 if (r_depthfirst.integer >= 2)
9799 R_DrawModelsDepth();
9800 if (r_timereport_active)
9801 R_TimeReport("modeldepth");
9804 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9806 R_DrawModelShadowMaps();
9807 R_ResetViewRendering3D();
9808 // don't let sound skip if going slow
9809 if (r_refdef.scene.extraupdate)
9813 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9815 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9816 if (r_timereport_active)
9817 R_TimeReport("world");
9820 // don't let sound skip if going slow
9821 if (r_refdef.scene.extraupdate)
9825 if (r_timereport_active)
9826 R_TimeReport("models");
9828 // don't let sound skip if going slow
9829 if (r_refdef.scene.extraupdate)
9832 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9834 R_DrawModelShadows();
9835 R_ResetViewRendering3D();
9836 // don't let sound skip if going slow
9837 if (r_refdef.scene.extraupdate)
9841 if (!r_shadow_usingdeferredprepass)
9843 R_Shadow_DrawLights();
9844 if (r_timereport_active)
9845 R_TimeReport("rtlights");
9848 // don't let sound skip if going slow
9849 if (r_refdef.scene.extraupdate)
9852 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9854 R_DrawModelShadows();
9855 R_ResetViewRendering3D();
9856 // don't let sound skip if going slow
9857 if (r_refdef.scene.extraupdate)
9861 if (cl.csqc_vidvars.drawworld)
9863 if (cl_decals_newsystem.integer)
9865 R_DrawModelDecals();
9866 if (r_timereport_active)
9867 R_TimeReport("modeldecals");
9872 if (r_timereport_active)
9873 R_TimeReport("decals");
9877 if (r_timereport_active)
9878 R_TimeReport("particles");
9881 if (r_timereport_active)
9882 R_TimeReport("explosions");
9884 R_DrawLightningBeams();
9885 if (r_timereport_active)
9886 R_TimeReport("lightning");
9889 VM_CL_AddPolygonsToMeshQueue();
9891 if (r_refdef.view.showdebug)
9893 if (cl_locs_show.integer)
9896 if (r_timereport_active)
9897 R_TimeReport("showlocs");
9900 if (r_drawportals.integer)
9903 if (r_timereport_active)
9904 R_TimeReport("portals");
9907 if (r_showbboxes.value > 0)
9909 R_DrawEntityBBoxes();
9910 if (r_timereport_active)
9911 R_TimeReport("bboxes");
9915 R_MeshQueue_RenderTransparent();
9916 if (r_timereport_active)
9917 R_TimeReport("drawtrans");
9919 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))
9921 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9922 if (r_timereport_active)
9923 R_TimeReport("worlddebug");
9924 R_DrawModelsDebug();
9925 if (r_timereport_active)
9926 R_TimeReport("modeldebug");
9929 if (cl.csqc_vidvars.drawworld)
9931 R_Shadow_DrawCoronas();
9932 if (r_timereport_active)
9933 R_TimeReport("coronas");
9938 GL_DepthTest(false);
9939 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9940 GL_Color(1, 1, 1, 1);
9941 qglBegin(GL_POLYGON);
9942 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9943 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9944 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9945 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9947 qglBegin(GL_POLYGON);
9948 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]);
9949 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]);
9950 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]);
9951 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]);
9953 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9957 // don't let sound skip if going slow
9958 if (r_refdef.scene.extraupdate)
9961 R_ResetViewRendering2D();
9964 static const unsigned short bboxelements[36] =
9974 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9977 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9979 RSurf_ActiveWorldEntity();
9981 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9982 GL_DepthMask(false);
9983 GL_DepthRange(0, 1);
9984 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9985 R_Mesh_ResetTextureState();
9987 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9988 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9989 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9990 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9991 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9992 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9993 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9994 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9995 R_FillColors(color4f, 8, cr, cg, cb, ca);
9996 if (r_refdef.fogenabled)
9998 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10000 f1 = RSurf_FogVertex(v);
10002 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10003 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10004 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10007 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10008 R_Mesh_ResetTextureState();
10009 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10010 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10013 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10017 prvm_edict_t *edict;
10018 prvm_prog_t *prog_save = prog;
10020 // this function draws bounding boxes of server entities
10024 GL_CullFace(GL_NONE);
10025 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10029 for (i = 0;i < numsurfaces;i++)
10031 edict = PRVM_EDICT_NUM(surfacelist[i]);
10032 switch ((int)edict->fields.server->solid)
10034 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
10035 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
10036 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
10037 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10038 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
10039 default: Vector4Set(color, 0, 0, 0, 0.50);break;
10041 color[3] *= r_showbboxes.value;
10042 color[3] = bound(0, color[3], 1);
10043 GL_DepthTest(!r_showdisabledepthtest.integer);
10044 GL_CullFace(r_refdef.view.cullface_front);
10045 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10051 static void R_DrawEntityBBoxes(void)
10054 prvm_edict_t *edict;
10056 prvm_prog_t *prog_save = prog;
10058 // this function draws bounding boxes of server entities
10064 for (i = 0;i < prog->num_edicts;i++)
10066 edict = PRVM_EDICT_NUM(i);
10067 if (edict->priv.server->free)
10069 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10070 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10072 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10074 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10075 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10081 static const int nomodelelement3i[24] =
10093 static const unsigned short nomodelelement3s[24] =
10105 static const float nomodelvertex3f[6*3] =
10115 static const float nomodelcolor4f[6*4] =
10117 0.0f, 0.0f, 0.5f, 1.0f,
10118 0.0f, 0.0f, 0.5f, 1.0f,
10119 0.0f, 0.5f, 0.0f, 1.0f,
10120 0.0f, 0.5f, 0.0f, 1.0f,
10121 0.5f, 0.0f, 0.0f, 1.0f,
10122 0.5f, 0.0f, 0.0f, 1.0f
10125 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10129 float color4f[6*4];
10131 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);
10133 // this is only called once per entity so numsurfaces is always 1, and
10134 // surfacelist is always {0}, so this code does not handle batches
10136 if (rsurface.ent_flags & RENDER_ADDITIVE)
10138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10139 GL_DepthMask(false);
10141 else if (rsurface.colormod[3] < 1)
10143 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10144 GL_DepthMask(false);
10148 GL_BlendFunc(GL_ONE, GL_ZERO);
10149 GL_DepthMask(true);
10151 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10152 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10153 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10154 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10155 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10156 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10157 for (i = 0, c = color4f;i < 6;i++, c += 4)
10159 c[0] *= rsurface.colormod[0];
10160 c[1] *= rsurface.colormod[1];
10161 c[2] *= rsurface.colormod[2];
10162 c[3] *= rsurface.colormod[3];
10164 if (r_refdef.fogenabled)
10166 for (i = 0, c = color4f;i < 6;i++, c += 4)
10168 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10170 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10171 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10172 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10175 R_Mesh_ResetTextureState();
10176 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10177 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10180 void R_DrawNoModel(entity_render_t *ent)
10183 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10184 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10185 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10187 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10190 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10192 vec3_t right1, right2, diff, normal;
10194 VectorSubtract (org2, org1, normal);
10196 // calculate 'right' vector for start
10197 VectorSubtract (r_refdef.view.origin, org1, diff);
10198 CrossProduct (normal, diff, right1);
10199 VectorNormalize (right1);
10201 // calculate 'right' vector for end
10202 VectorSubtract (r_refdef.view.origin, org2, diff);
10203 CrossProduct (normal, diff, right2);
10204 VectorNormalize (right2);
10206 vert[ 0] = org1[0] + width * right1[0];
10207 vert[ 1] = org1[1] + width * right1[1];
10208 vert[ 2] = org1[2] + width * right1[2];
10209 vert[ 3] = org1[0] - width * right1[0];
10210 vert[ 4] = org1[1] - width * right1[1];
10211 vert[ 5] = org1[2] - width * right1[2];
10212 vert[ 6] = org2[0] - width * right2[0];
10213 vert[ 7] = org2[1] - width * right2[1];
10214 vert[ 8] = org2[2] - width * right2[2];
10215 vert[ 9] = org2[0] + width * right2[0];
10216 vert[10] = org2[1] + width * right2[1];
10217 vert[11] = org2[2] + width * right2[2];
10220 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)
10222 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10223 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10224 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10225 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10226 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10227 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10228 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10229 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10230 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10231 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10232 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10233 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10236 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10241 VectorSet(v, x, y, z);
10242 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10243 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10245 if (i == mesh->numvertices)
10247 if (mesh->numvertices < mesh->maxvertices)
10249 VectorCopy(v, vertex3f);
10250 mesh->numvertices++;
10252 return mesh->numvertices;
10258 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10261 int *e, element[3];
10262 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10263 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10264 e = mesh->element3i + mesh->numtriangles * 3;
10265 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10267 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10268 if (mesh->numtriangles < mesh->maxtriangles)
10273 mesh->numtriangles++;
10275 element[1] = element[2];
10279 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10282 int *e, element[3];
10283 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10284 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10285 e = mesh->element3i + mesh->numtriangles * 3;
10286 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10288 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10289 if (mesh->numtriangles < mesh->maxtriangles)
10294 mesh->numtriangles++;
10296 element[1] = element[2];
10300 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10301 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10303 int planenum, planenum2;
10306 mplane_t *plane, *plane2;
10308 double temppoints[2][256*3];
10309 // figure out how large a bounding box we need to properly compute this brush
10311 for (w = 0;w < numplanes;w++)
10312 maxdist = max(maxdist, fabs(planes[w].dist));
10313 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10314 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10315 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10319 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10320 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10322 if (planenum2 == planenum)
10324 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);
10327 if (tempnumpoints < 3)
10329 // generate elements forming a triangle fan for this polygon
10330 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10334 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)
10336 texturelayer_t *layer;
10337 layer = t->currentlayers + t->currentnumlayers++;
10338 layer->type = type;
10339 layer->depthmask = depthmask;
10340 layer->blendfunc1 = blendfunc1;
10341 layer->blendfunc2 = blendfunc2;
10342 layer->texture = texture;
10343 layer->texmatrix = *matrix;
10344 layer->color[0] = r;
10345 layer->color[1] = g;
10346 layer->color[2] = b;
10347 layer->color[3] = a;
10350 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10352 if(parms[0] == 0 && parms[1] == 0)
10354 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10355 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10360 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10363 index = parms[2] + r_refdef.scene.time * parms[3];
10364 index -= floor(index);
10365 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10368 case Q3WAVEFUNC_NONE:
10369 case Q3WAVEFUNC_NOISE:
10370 case Q3WAVEFUNC_COUNT:
10373 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10374 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10375 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10376 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10377 case Q3WAVEFUNC_TRIANGLE:
10379 f = index - floor(index);
10382 else if (index < 2)
10384 else if (index < 3)
10390 f = parms[0] + parms[1] * f;
10391 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10392 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10396 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10401 matrix4x4_t matrix, temp;
10402 switch(tcmod->tcmod)
10404 case Q3TCMOD_COUNT:
10406 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10407 matrix = r_waterscrollmatrix;
10409 matrix = identitymatrix;
10411 case Q3TCMOD_ENTITYTRANSLATE:
10412 // this is used in Q3 to allow the gamecode to control texcoord
10413 // scrolling on the entity, which is not supported in darkplaces yet.
10414 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10416 case Q3TCMOD_ROTATE:
10417 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10418 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10419 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10421 case Q3TCMOD_SCALE:
10422 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10424 case Q3TCMOD_SCROLL:
10425 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10427 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10428 w = (int) tcmod->parms[0];
10429 h = (int) tcmod->parms[1];
10430 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10432 idx = (int) floor(f * w * h);
10433 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10435 case Q3TCMOD_STRETCH:
10436 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10437 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10439 case Q3TCMOD_TRANSFORM:
10440 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
10441 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
10442 VectorSet(tcmat + 6, 0 , 0 , 1);
10443 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
10444 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10446 case Q3TCMOD_TURBULENT:
10447 // this is handled in the RSurf_PrepareVertices function
10448 matrix = identitymatrix;
10452 Matrix4x4_Concat(texmatrix, &matrix, &temp);
10455 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10457 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10458 char name[MAX_QPATH];
10459 skinframe_t *skinframe;
10460 unsigned char pixels[296*194];
10461 strlcpy(cache->name, skinname, sizeof(cache->name));
10462 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10463 if (developer_loading.integer)
10464 Con_Printf("loading %s\n", name);
10465 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10466 if (!skinframe || !skinframe->base)
10469 fs_offset_t filesize;
10471 f = FS_LoadFile(name, tempmempool, true, &filesize);
10474 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10475 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10479 cache->skinframe = skinframe;
10482 texture_t *R_GetCurrentTexture(texture_t *t)
10485 const entity_render_t *ent = rsurface.entity;
10486 dp_model_t *model = ent->model;
10487 q3shaderinfo_layer_tcmod_t *tcmod;
10489 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10490 return t->currentframe;
10491 t->update_lastrenderframe = r_textureframe;
10492 t->update_lastrenderentity = (void *)ent;
10494 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10495 t->camera_entity = ent->entitynumber;
10497 t->camera_entity = 0;
10499 // switch to an alternate material if this is a q1bsp animated material
10501 texture_t *texture = t;
10502 int s = rsurface.ent_skinnum;
10503 if ((unsigned int)s >= (unsigned int)model->numskins)
10505 if (model->skinscenes)
10507 if (model->skinscenes[s].framecount > 1)
10508 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10510 s = model->skinscenes[s].firstframe;
10513 t = t + s * model->num_surfaces;
10516 // use an alternate animation if the entity's frame is not 0,
10517 // and only if the texture has an alternate animation
10518 if (rsurface.ent_alttextures && t->anim_total[1])
10519 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10521 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10523 texture->currentframe = t;
10526 // update currentskinframe to be a qw skin or animation frame
10527 if (rsurface.ent_qwskin >= 0)
10529 i = rsurface.ent_qwskin;
10530 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10532 r_qwskincache_size = cl.maxclients;
10534 Mem_Free(r_qwskincache);
10535 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10537 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10538 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10539 t->currentskinframe = r_qwskincache[i].skinframe;
10540 if (t->currentskinframe == NULL)
10541 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10543 else if (t->numskinframes >= 2)
10544 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10545 if (t->backgroundnumskinframes >= 2)
10546 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10548 t->currentmaterialflags = t->basematerialflags;
10549 t->currentalpha = rsurface.colormod[3];
10550 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10551 t->currentalpha *= r_wateralpha.value;
10552 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10553 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10554 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10555 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10556 if (!(rsurface.ent_flags & RENDER_LIGHT))
10557 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10558 else if (FAKELIGHT_ENABLED)
10560 // no modellight if using fakelight for the map
10562 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10564 // pick a model lighting mode
10565 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10566 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10568 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10570 if (rsurface.ent_flags & RENDER_ADDITIVE)
10571 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10572 else if (t->currentalpha < 1)
10573 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10574 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10575 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10576 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10577 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10578 if (t->backgroundnumskinframes)
10579 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10580 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10582 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10583 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10586 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10587 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10588 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10590 // there is no tcmod
10591 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10593 t->currenttexmatrix = r_waterscrollmatrix;
10594 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10596 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10598 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10599 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10602 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10603 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10604 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10605 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10607 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10608 if (t->currentskinframe->qpixels)
10609 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10610 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10611 if (!t->basetexture)
10612 t->basetexture = r_texture_notexture;
10613 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10614 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10615 t->nmaptexture = t->currentskinframe->nmap;
10616 if (!t->nmaptexture)
10617 t->nmaptexture = r_texture_blanknormalmap;
10618 t->glosstexture = r_texture_black;
10619 t->glowtexture = t->currentskinframe->glow;
10620 t->fogtexture = t->currentskinframe->fog;
10621 t->reflectmasktexture = t->currentskinframe->reflect;
10622 if (t->backgroundnumskinframes)
10624 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10625 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10626 t->backgroundglosstexture = r_texture_black;
10627 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10628 if (!t->backgroundnmaptexture)
10629 t->backgroundnmaptexture = r_texture_blanknormalmap;
10633 t->backgroundbasetexture = r_texture_white;
10634 t->backgroundnmaptexture = r_texture_blanknormalmap;
10635 t->backgroundglosstexture = r_texture_black;
10636 t->backgroundglowtexture = NULL;
10638 t->specularpower = r_shadow_glossexponent.value;
10639 // TODO: store reference values for these in the texture?
10640 t->specularscale = 0;
10641 if (r_shadow_gloss.integer > 0)
10643 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10645 if (r_shadow_glossintensity.value > 0)
10647 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10648 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10649 t->specularscale = r_shadow_glossintensity.value;
10652 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10654 t->glosstexture = r_texture_white;
10655 t->backgroundglosstexture = r_texture_white;
10656 t->specularscale = r_shadow_gloss2intensity.value;
10657 t->specularpower = r_shadow_gloss2exponent.value;
10660 t->specularscale *= t->specularscalemod;
10661 t->specularpower *= t->specularpowermod;
10663 // lightmaps mode looks bad with dlights using actual texturing, so turn
10664 // off the colormap and glossmap, but leave the normalmap on as it still
10665 // accurately represents the shading involved
10666 if (gl_lightmaps.integer)
10668 t->basetexture = r_texture_grey128;
10669 t->pantstexture = r_texture_black;
10670 t->shirttexture = r_texture_black;
10671 t->nmaptexture = r_texture_blanknormalmap;
10672 t->glosstexture = r_texture_black;
10673 t->glowtexture = NULL;
10674 t->fogtexture = NULL;
10675 t->reflectmasktexture = NULL;
10676 t->backgroundbasetexture = NULL;
10677 t->backgroundnmaptexture = r_texture_blanknormalmap;
10678 t->backgroundglosstexture = r_texture_black;
10679 t->backgroundglowtexture = NULL;
10680 t->specularscale = 0;
10681 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10684 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10685 VectorClear(t->dlightcolor);
10686 t->currentnumlayers = 0;
10687 if (t->currentmaterialflags & MATERIALFLAG_WALL)
10689 int blendfunc1, blendfunc2;
10690 qboolean depthmask;
10691 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10693 blendfunc1 = GL_SRC_ALPHA;
10694 blendfunc2 = GL_ONE;
10696 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10698 blendfunc1 = GL_SRC_ALPHA;
10699 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10701 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10703 blendfunc1 = t->customblendfunc[0];
10704 blendfunc2 = t->customblendfunc[1];
10708 blendfunc1 = GL_ONE;
10709 blendfunc2 = GL_ZERO;
10711 // don't colormod evilblend textures
10712 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10713 VectorSet(t->lightmapcolor, 1, 1, 1);
10714 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10715 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10717 // fullbright is not affected by r_refdef.lightmapintensity
10718 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]);
10719 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10720 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]);
10721 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10722 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]);
10726 vec3_t ambientcolor;
10728 // set the color tint used for lights affecting this surface
10729 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10731 // q3bsp has no lightmap updates, so the lightstylevalue that
10732 // would normally be baked into the lightmap must be
10733 // applied to the color
10734 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10735 if (model->type == mod_brushq3)
10736 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10737 colorscale *= r_refdef.lightmapintensity;
10738 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10739 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10740 // basic lit geometry
10741 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]);
10742 // add pants/shirt if needed
10743 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10744 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]);
10745 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10746 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]);
10747 // now add ambient passes if needed
10748 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10750 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]);
10751 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10752 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]);
10753 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10754 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]);
10757 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10758 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]);
10759 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10761 // if this is opaque use alpha blend which will darken the earlier
10764 // if this is an alpha blended material, all the earlier passes
10765 // were darkened by fog already, so we only need to add the fog
10766 // color ontop through the fog mask texture
10768 // if this is an additive blended material, all the earlier passes
10769 // were darkened by fog already, and we should not add fog color
10770 // (because the background was not darkened, there is no fog color
10771 // that was lost behind it).
10772 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]);
10776 return t->currentframe;
10779 rsurfacestate_t rsurface;
10781 void R_Mesh_ResizeArrays(int newvertices)
10783 unsigned char *base;
10785 if (rsurface.array_size >= newvertices)
10787 if (rsurface.array_base)
10788 Mem_Free(rsurface.array_base);
10789 rsurface.array_size = (newvertices + 1023) & ~1023;
10791 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10792 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10793 size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10794 size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10795 size += rsurface.array_size * sizeof(float[3]);
10796 size += rsurface.array_size * sizeof(float[3]);
10797 size += rsurface.array_size * sizeof(float[3]);
10798 size += rsurface.array_size * sizeof(float[3]);
10799 size += rsurface.array_size * sizeof(float[3]);
10800 size += rsurface.array_size * sizeof(float[3]);
10801 size += rsurface.array_size * sizeof(float[3]);
10802 size += rsurface.array_size * sizeof(float[3]);
10803 size += rsurface.array_size * sizeof(float[4]);
10804 size += rsurface.array_size * sizeof(float[2]);
10805 size += rsurface.array_size * sizeof(float[2]);
10806 size += rsurface.array_size * sizeof(float[4]);
10807 size += rsurface.array_size * sizeof(int[3]);
10808 size += rsurface.array_size * sizeof(unsigned short[3]);
10809 rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10810 rsurface.array_modelvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10811 rsurface.array_batchvertexmesh = (r_vertexmesh_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10812 rsurface.array_modelvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10813 rsurface.array_batchvertexposition = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10814 rsurface.array_modelvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10815 rsurface.array_modelsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10816 rsurface.array_modeltvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10817 rsurface.array_modelnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10818 rsurface.array_batchvertex3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10819 rsurface.array_batchsvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10820 rsurface.array_batchtvector3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10821 rsurface.array_batchnormal3f = (float *)base;base += rsurface.array_size * sizeof(float[3]);
10822 rsurface.array_batchlightmapcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10823 rsurface.array_batchtexcoordtexture2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10824 rsurface.array_batchtexcoordlightmap2f = (float *)base;base += rsurface.array_size * sizeof(float[2]);
10825 rsurface.array_passcolor4f = (float *)base;base += rsurface.array_size * sizeof(float[4]);
10826 rsurface.array_batchelement3i = (int *)base;base += rsurface.array_size * sizeof(int[3]);
10827 rsurface.array_batchelement3s = (unsigned short *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10830 void RSurf_ActiveWorldEntity(void)
10832 dp_model_t *model = r_refdef.scene.worldmodel;
10833 //if (rsurface.entity == r_refdef.scene.worldentity)
10835 rsurface.entity = r_refdef.scene.worldentity;
10836 rsurface.skeleton = NULL;
10837 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10838 rsurface.ent_skinnum = 0;
10839 rsurface.ent_qwskin = -1;
10840 rsurface.ent_shadertime = 0;
10841 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10842 R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10843 rsurface.matrix = identitymatrix;
10844 rsurface.inversematrix = identitymatrix;
10845 rsurface.matrixscale = 1;
10846 rsurface.inversematrixscale = 1;
10847 R_EntityMatrix(&identitymatrix);
10848 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10849 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10850 rsurface.fograngerecip = r_refdef.fograngerecip;
10851 rsurface.fogheightfade = r_refdef.fogheightfade;
10852 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10853 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10854 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10855 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10856 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10857 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10858 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10859 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10860 rsurface.colormod[3] = 1;
10861 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);
10862 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10863 rsurface.frameblend[0].lerp = 1;
10864 rsurface.ent_alttextures = false;
10865 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10866 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10867 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
10868 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10869 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10870 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10871 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10872 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10873 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10874 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10875 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10876 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
10877 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10878 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10879 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
10880 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10881 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10882 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
10883 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10884 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10885 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
10886 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10887 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10888 rsurface.modelelement3i = model->surfmesh.data_element3i;
10889 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10890 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10891 rsurface.modelelement3s = model->surfmesh.data_element3s;
10892 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10893 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10894 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10895 rsurface.modelnumvertices = model->surfmesh.num_vertices;
10896 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10897 rsurface.modelsurfaces = model->data_surfaces;
10898 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10899 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10900 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10901 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10902 rsurface.modelgeneratedvertex = false;
10903 rsurface.batchgeneratedvertex = false;
10904 rsurface.batchfirstvertex = 0;
10905 rsurface.batchnumvertices = 0;
10906 rsurface.batchfirsttriangle = 0;
10907 rsurface.batchnumtriangles = 0;
10908 rsurface.batchvertex3f = NULL;
10909 rsurface.batchvertex3f_vertexbuffer = NULL;
10910 rsurface.batchvertex3f_bufferoffset = 0;
10911 rsurface.batchsvector3f = NULL;
10912 rsurface.batchsvector3f_vertexbuffer = NULL;
10913 rsurface.batchsvector3f_bufferoffset = 0;
10914 rsurface.batchtvector3f = NULL;
10915 rsurface.batchtvector3f_vertexbuffer = NULL;
10916 rsurface.batchtvector3f_bufferoffset = 0;
10917 rsurface.batchnormal3f = NULL;
10918 rsurface.batchnormal3f_vertexbuffer = NULL;
10919 rsurface.batchnormal3f_bufferoffset = 0;
10920 rsurface.batchlightmapcolor4f = NULL;
10921 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10922 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10923 rsurface.batchtexcoordtexture2f = NULL;
10924 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10925 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10926 rsurface.batchtexcoordlightmap2f = NULL;
10927 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10928 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10929 rsurface.batchvertexmesh = NULL;
10930 rsurface.batchvertexmeshbuffer = NULL;
10931 rsurface.batchvertexposition = NULL;
10932 rsurface.batchvertexpositionbuffer = NULL;
10933 rsurface.batchelement3i = NULL;
10934 rsurface.batchelement3i_indexbuffer = NULL;
10935 rsurface.batchelement3i_bufferoffset = 0;
10936 rsurface.batchelement3s = NULL;
10937 rsurface.batchelement3s_indexbuffer = NULL;
10938 rsurface.batchelement3s_bufferoffset = 0;
10939 rsurface.passcolor4f = NULL;
10940 rsurface.passcolor4f_vertexbuffer = NULL;
10941 rsurface.passcolor4f_bufferoffset = 0;
10944 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10946 dp_model_t *model = ent->model;
10947 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10949 rsurface.entity = (entity_render_t *)ent;
10950 rsurface.skeleton = ent->skeleton;
10951 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10952 rsurface.ent_skinnum = ent->skinnum;
10953 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;
10954 rsurface.ent_shadertime = ent->shadertime;
10955 rsurface.ent_flags = ent->flags;
10956 R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10957 rsurface.matrix = ent->matrix;
10958 rsurface.inversematrix = ent->inversematrix;
10959 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10960 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10961 R_EntityMatrix(&rsurface.matrix);
10962 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10963 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10964 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10965 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10966 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10967 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10968 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10969 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10970 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10971 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10972 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10973 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10974 rsurface.colormod[3] = ent->alpha;
10975 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10976 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10977 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10978 rsurface.basepolygonfactor = r_refdef.polygonfactor;
10979 rsurface.basepolygonoffset = r_refdef.polygonoffset;
10980 if (ent->model->brush.submodel && !prepass)
10982 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10983 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10985 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10987 if (ent->animcache_vertex3f && !r_framedata_failed)
10989 rsurface.modelvertex3f = ent->animcache_vertex3f;
10990 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10991 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10992 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10993 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10994 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10995 rsurface.modelvertexposition = ent->animcache_vertexposition;
10996 rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10998 else if (wanttangents)
11000 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11001 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11002 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11003 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11004 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11005 rsurface.modelvertexmesh = NULL;
11006 rsurface.modelvertexmeshbuffer = NULL;
11007 rsurface.modelvertexposition = NULL;
11008 rsurface.modelvertexpositionbuffer = NULL;
11010 else if (wantnormals)
11012 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11013 rsurface.modelsvector3f = NULL;
11014 rsurface.modeltvector3f = NULL;
11015 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11016 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11017 rsurface.modelvertexmesh = NULL;
11018 rsurface.modelvertexmeshbuffer = NULL;
11019 rsurface.modelvertexposition = NULL;
11020 rsurface.modelvertexpositionbuffer = NULL;
11024 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11025 rsurface.modelsvector3f = NULL;
11026 rsurface.modeltvector3f = NULL;
11027 rsurface.modelnormal3f = NULL;
11028 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11029 rsurface.modelvertexmesh = NULL;
11030 rsurface.modelvertexmeshbuffer = NULL;
11031 rsurface.modelvertexposition = NULL;
11032 rsurface.modelvertexpositionbuffer = NULL;
11034 rsurface.modelvertex3f_vertexbuffer = 0;
11035 rsurface.modelvertex3f_bufferoffset = 0;
11036 rsurface.modelsvector3f_vertexbuffer = 0;
11037 rsurface.modelsvector3f_bufferoffset = 0;
11038 rsurface.modeltvector3f_vertexbuffer = 0;
11039 rsurface.modeltvector3f_bufferoffset = 0;
11040 rsurface.modelnormal3f_vertexbuffer = 0;
11041 rsurface.modelnormal3f_bufferoffset = 0;
11042 rsurface.modelgeneratedvertex = true;
11046 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
11047 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11048 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11049 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11050 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11051 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11052 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11053 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11054 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11055 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
11056 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11057 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11058 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11059 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11060 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11061 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11062 rsurface.modelgeneratedvertex = false;
11064 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
11065 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11066 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11067 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
11068 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11069 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11070 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
11071 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11072 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11073 rsurface.modelelement3i = model->surfmesh.data_element3i;
11074 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11075 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11076 rsurface.modelelement3s = model->surfmesh.data_element3s;
11077 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11078 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11079 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11080 rsurface.modelnumvertices = model->surfmesh.num_vertices;
11081 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11082 rsurface.modelsurfaces = model->data_surfaces;
11083 rsurface.batchgeneratedvertex = false;
11084 rsurface.batchfirstvertex = 0;
11085 rsurface.batchnumvertices = 0;
11086 rsurface.batchfirsttriangle = 0;
11087 rsurface.batchnumtriangles = 0;
11088 rsurface.batchvertex3f = NULL;
11089 rsurface.batchvertex3f_vertexbuffer = NULL;
11090 rsurface.batchvertex3f_bufferoffset = 0;
11091 rsurface.batchsvector3f = NULL;
11092 rsurface.batchsvector3f_vertexbuffer = NULL;
11093 rsurface.batchsvector3f_bufferoffset = 0;
11094 rsurface.batchtvector3f = NULL;
11095 rsurface.batchtvector3f_vertexbuffer = NULL;
11096 rsurface.batchtvector3f_bufferoffset = 0;
11097 rsurface.batchnormal3f = NULL;
11098 rsurface.batchnormal3f_vertexbuffer = NULL;
11099 rsurface.batchnormal3f_bufferoffset = 0;
11100 rsurface.batchlightmapcolor4f = NULL;
11101 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11102 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11103 rsurface.batchtexcoordtexture2f = NULL;
11104 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11105 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11106 rsurface.batchtexcoordlightmap2f = NULL;
11107 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11108 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11109 rsurface.batchvertexmesh = NULL;
11110 rsurface.batchvertexmeshbuffer = NULL;
11111 rsurface.batchvertexposition = NULL;
11112 rsurface.batchvertexpositionbuffer = NULL;
11113 rsurface.batchelement3i = NULL;
11114 rsurface.batchelement3i_indexbuffer = NULL;
11115 rsurface.batchelement3i_bufferoffset = 0;
11116 rsurface.batchelement3s = NULL;
11117 rsurface.batchelement3s_indexbuffer = NULL;
11118 rsurface.batchelement3s_bufferoffset = 0;
11119 rsurface.passcolor4f = NULL;
11120 rsurface.passcolor4f_vertexbuffer = NULL;
11121 rsurface.passcolor4f_bufferoffset = 0;
11124 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)
11128 rsurface.entity = r_refdef.scene.worldentity;
11129 rsurface.skeleton = NULL;
11130 rsurface.ent_skinnum = 0;
11131 rsurface.ent_qwskin = -1;
11132 rsurface.ent_shadertime = shadertime;
11133 rsurface.ent_flags = entflags;
11134 rsurface.modelnumvertices = numvertices;
11135 rsurface.modelnumtriangles = numtriangles;
11136 R_Mesh_ResizeArrays(max(rsurface.modelnumvertices, rsurface.modelnumtriangles));
11137 rsurface.matrix = *matrix;
11138 rsurface.inversematrix = *inversematrix;
11139 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11140 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11141 R_EntityMatrix(&rsurface.matrix);
11142 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11143 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11144 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11145 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11146 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11147 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11148 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11149 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11150 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11151 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11152 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11153 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11154 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);
11155 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11156 rsurface.frameblend[0].lerp = 1;
11157 rsurface.ent_alttextures = false;
11158 rsurface.basepolygonfactor = r_refdef.polygonfactor;
11159 rsurface.basepolygonoffset = r_refdef.polygonoffset;
11162 rsurface.modelvertex3f = vertex3f;
11163 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11164 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11165 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11167 else if (wantnormals)
11169 rsurface.modelvertex3f = vertex3f;
11170 rsurface.modelsvector3f = NULL;
11171 rsurface.modeltvector3f = NULL;
11172 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11176 rsurface.modelvertex3f = vertex3f;
11177 rsurface.modelsvector3f = NULL;
11178 rsurface.modeltvector3f = NULL;
11179 rsurface.modelnormal3f = NULL;
11181 rsurface.modelvertexmesh = NULL;
11182 rsurface.modelvertexmeshbuffer = NULL;
11183 rsurface.modelvertexposition = NULL;
11184 rsurface.modelvertexpositionbuffer = NULL;
11185 rsurface.modelvertex3f_vertexbuffer = 0;
11186 rsurface.modelvertex3f_bufferoffset = 0;
11187 rsurface.modelsvector3f_vertexbuffer = 0;
11188 rsurface.modelsvector3f_bufferoffset = 0;
11189 rsurface.modeltvector3f_vertexbuffer = 0;
11190 rsurface.modeltvector3f_bufferoffset = 0;
11191 rsurface.modelnormal3f_vertexbuffer = 0;
11192 rsurface.modelnormal3f_bufferoffset = 0;
11193 rsurface.modelgeneratedvertex = true;
11194 rsurface.modellightmapcolor4f = color4f;
11195 rsurface.modellightmapcolor4f_vertexbuffer = 0;
11196 rsurface.modellightmapcolor4f_bufferoffset = 0;
11197 rsurface.modeltexcoordtexture2f = texcoord2f;
11198 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11199 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11200 rsurface.modeltexcoordlightmap2f = NULL;
11201 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11202 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11203 rsurface.modelelement3i = element3i;
11204 rsurface.modelelement3i_indexbuffer = NULL;
11205 rsurface.modelelement3i_bufferoffset = 0;
11206 rsurface.modelelement3s = element3s;
11207 rsurface.modelelement3s_indexbuffer = NULL;
11208 rsurface.modelelement3s_bufferoffset = 0;
11209 rsurface.modellightmapoffsets = NULL;
11210 rsurface.modelsurfaces = NULL;
11211 rsurface.batchgeneratedvertex = false;
11212 rsurface.batchfirstvertex = 0;
11213 rsurface.batchnumvertices = 0;
11214 rsurface.batchfirsttriangle = 0;
11215 rsurface.batchnumtriangles = 0;
11216 rsurface.batchvertex3f = NULL;
11217 rsurface.batchvertex3f_vertexbuffer = NULL;
11218 rsurface.batchvertex3f_bufferoffset = 0;
11219 rsurface.batchsvector3f = NULL;
11220 rsurface.batchsvector3f_vertexbuffer = NULL;
11221 rsurface.batchsvector3f_bufferoffset = 0;
11222 rsurface.batchtvector3f = NULL;
11223 rsurface.batchtvector3f_vertexbuffer = NULL;
11224 rsurface.batchtvector3f_bufferoffset = 0;
11225 rsurface.batchnormal3f = NULL;
11226 rsurface.batchnormal3f_vertexbuffer = NULL;
11227 rsurface.batchnormal3f_bufferoffset = 0;
11228 rsurface.batchlightmapcolor4f = NULL;
11229 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11230 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11231 rsurface.batchtexcoordtexture2f = NULL;
11232 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11233 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11234 rsurface.batchtexcoordlightmap2f = NULL;
11235 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11236 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11237 rsurface.batchvertexmesh = NULL;
11238 rsurface.batchvertexmeshbuffer = NULL;
11239 rsurface.batchvertexposition = NULL;
11240 rsurface.batchvertexpositionbuffer = NULL;
11241 rsurface.batchelement3i = NULL;
11242 rsurface.batchelement3i_indexbuffer = NULL;
11243 rsurface.batchelement3i_bufferoffset = 0;
11244 rsurface.batchelement3s = NULL;
11245 rsurface.batchelement3s_indexbuffer = NULL;
11246 rsurface.batchelement3s_bufferoffset = 0;
11247 rsurface.passcolor4f = NULL;
11248 rsurface.passcolor4f_vertexbuffer = NULL;
11249 rsurface.passcolor4f_bufferoffset = 0;
11251 if (rsurface.modelnumvertices && rsurface.modelelement3i)
11253 if ((wantnormals || wanttangents) && !normal3f)
11255 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11256 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11258 if (wanttangents && !svector3f)
11260 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);
11261 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11262 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11266 // now convert arrays into vertexmesh structs
11267 for (i = 0;i < numvertices;i++)
11269 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11270 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11271 if (rsurface.modelsvector3f)
11272 VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11273 if (rsurface.modeltvector3f)
11274 VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11275 if (rsurface.modelnormal3f)
11276 VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11277 if (rsurface.modellightmapcolor4f)
11278 Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11279 if (rsurface.modeltexcoordtexture2f)
11280 Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11281 if (rsurface.modeltexcoordlightmap2f)
11282 Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11286 float RSurf_FogPoint(const float *v)
11288 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11289 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11290 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11291 float FogHeightFade = r_refdef.fogheightfade;
11293 unsigned int fogmasktableindex;
11294 if (r_refdef.fogplaneviewabove)
11295 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11297 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11298 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11299 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11302 float RSurf_FogVertex(const float *v)
11304 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11305 float FogPlaneViewDist = rsurface.fogplaneviewdist;
11306 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11307 float FogHeightFade = rsurface.fogheightfade;
11309 unsigned int fogmasktableindex;
11310 if (r_refdef.fogplaneviewabove)
11311 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11313 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11314 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11315 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11318 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11321 for (i = 0;i < numelements;i++)
11322 outelement3i[i] = inelement3i[i] + adjust;
11325 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11326 extern cvar_t gl_vbo;
11327 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11335 int surfacefirsttriangle;
11336 int surfacenumtriangles;
11337 int surfacefirstvertex;
11338 int surfaceendvertex;
11339 int surfacenumvertices;
11343 qboolean dynamicvertex;
11347 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11348 float waveparms[4];
11349 q3shaderinfo_deform_t *deform;
11350 const msurface_t *surface, *firstsurface;
11351 r_vertexposition_t *vertexposition;
11352 r_vertexmesh_t *vertexmesh;
11353 if (!texturenumsurfaces)
11355 // find vertex range of this surface batch
11357 firstsurface = texturesurfacelist[0];
11358 firsttriangle = firstsurface->num_firsttriangle;
11360 firstvertex = endvertex = firstsurface->num_firstvertex;
11361 for (i = 0;i < texturenumsurfaces;i++)
11363 surface = texturesurfacelist[i];
11364 if (surface != firstsurface + i)
11366 surfacefirstvertex = surface->num_firstvertex;
11367 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11368 surfacenumtriangles = surface->num_triangles;
11369 if (firstvertex > surfacefirstvertex)
11370 firstvertex = surfacefirstvertex;
11371 if (endvertex < surfaceendvertex)
11372 endvertex = surfaceendvertex;
11373 numtriangles += surfacenumtriangles;
11378 // we now know the vertex range used, and if there are any gaps in it
11379 rsurface.batchfirstvertex = firstvertex;
11380 rsurface.batchnumvertices = endvertex - firstvertex;
11381 rsurface.batchfirsttriangle = firsttriangle;
11382 rsurface.batchnumtriangles = numtriangles;
11384 // this variable holds flags for which properties have been updated that
11385 // may require regenerating vertexmesh or vertexposition arrays...
11388 // check if any dynamic vertex processing must occur
11389 dynamicvertex = false;
11391 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11392 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11393 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11395 switch (deform->deform)
11398 case Q3DEFORM_PROJECTIONSHADOW:
11399 case Q3DEFORM_TEXT0:
11400 case Q3DEFORM_TEXT1:
11401 case Q3DEFORM_TEXT2:
11402 case Q3DEFORM_TEXT3:
11403 case Q3DEFORM_TEXT4:
11404 case Q3DEFORM_TEXT5:
11405 case Q3DEFORM_TEXT6:
11406 case Q3DEFORM_TEXT7:
11407 case Q3DEFORM_NONE:
11409 case Q3DEFORM_AUTOSPRITE:
11410 dynamicvertex = true;
11411 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11412 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11414 case Q3DEFORM_AUTOSPRITE2:
11415 dynamicvertex = true;
11416 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11417 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11419 case Q3DEFORM_NORMAL:
11420 dynamicvertex = true;
11421 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11422 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11424 case Q3DEFORM_WAVE:
11425 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11426 break; // if wavefunc is a nop, ignore this transform
11427 dynamicvertex = true;
11428 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11429 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11431 case Q3DEFORM_BULGE:
11432 dynamicvertex = true;
11433 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11434 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11436 case Q3DEFORM_MOVE:
11437 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11438 break; // if wavefunc is a nop, ignore this transform
11439 dynamicvertex = true;
11440 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11441 needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11445 switch(rsurface.texture->tcgen.tcgen)
11448 case Q3TCGEN_TEXTURE:
11450 case Q3TCGEN_LIGHTMAP:
11451 dynamicvertex = true;
11452 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11453 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11455 case Q3TCGEN_VECTOR:
11456 dynamicvertex = true;
11457 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11458 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11460 case Q3TCGEN_ENVIRONMENT:
11461 dynamicvertex = true;
11462 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11463 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11466 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11468 dynamicvertex = true;
11469 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11470 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11473 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11475 dynamicvertex = true;
11476 batchneed |= BATCHNEED_NOGAPS;
11477 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11480 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11482 dynamicvertex = true;
11483 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11484 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11487 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11489 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11490 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
11491 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
11492 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
11493 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11494 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11495 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11498 // when the model data has no vertex buffer (dynamic mesh), we need to
11500 if (!rsurface.modelvertexmeshbuffer)
11501 batchneed |= BATCHNEED_NOGAPS;
11503 // if needsupdate, we have to do a dynamic vertex batch for sure
11504 if (needsupdate & batchneed)
11505 dynamicvertex = true;
11507 // see if we need to build vertexmesh from arrays
11508 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11509 dynamicvertex = true;
11511 // see if we need to build vertexposition from arrays
11512 if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11513 dynamicvertex = true;
11515 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11516 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11517 dynamicvertex = true;
11519 // if there is a chance of animated vertex colors, it's a dynamic batch
11520 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11521 dynamicvertex = true;
11523 rsurface.batchvertex3f = rsurface.modelvertex3f;
11524 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11525 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11526 rsurface.batchsvector3f = rsurface.modelsvector3f;
11527 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11528 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11529 rsurface.batchtvector3f = rsurface.modeltvector3f;
11530 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11531 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11532 rsurface.batchnormal3f = rsurface.modelnormal3f;
11533 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11534 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11535 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11536 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
11537 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11538 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11539 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
11540 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
11541 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11542 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11543 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11544 rsurface.batchvertexposition = rsurface.modelvertexposition;
11545 rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11546 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11547 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11548 rsurface.batchelement3i = rsurface.modelelement3i;
11549 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11550 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11551 rsurface.batchelement3s = rsurface.modelelement3s;
11552 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11553 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11555 // if any dynamic vertex processing has to occur in software, we copy the
11556 // entire surface list together before processing to rebase the vertices
11557 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11559 // if any gaps exist and we do not have a static vertex buffer, we have to
11560 // copy the surface list together to avoid wasting upload bandwidth on the
11561 // vertices in the gaps.
11563 // if gaps exist and we have a static vertex buffer, we still have to
11564 // combine the index buffer ranges into one dynamic index buffer.
11566 // in all cases we end up with data that can be drawn in one call.
11568 if (!dynamicvertex)
11570 // static vertex data, just set pointers...
11571 rsurface.batchgeneratedvertex = false;
11572 // if there are gaps, we want to build a combined index buffer,
11573 // otherwise use the original static buffer with an appropriate offset
11578 for (i = 0;i < texturenumsurfaces;i++)
11580 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11581 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11582 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11583 numtriangles += surfacenumtriangles;
11585 rsurface.batchelement3i = rsurface.array_batchelement3i;
11586 rsurface.batchelement3i_indexbuffer = NULL;
11587 rsurface.batchelement3i_bufferoffset = 0;
11588 rsurface.batchelement3s = NULL;
11589 rsurface.batchelement3s_indexbuffer = NULL;
11590 rsurface.batchelement3s_bufferoffset = 0;
11591 if (endvertex <= 65536)
11593 rsurface.batchelement3s = rsurface.array_batchelement3s;
11594 for (i = 0;i < numtriangles*3;i++)
11595 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11597 rsurface.batchfirsttriangle = firsttriangle;
11598 rsurface.batchnumtriangles = numtriangles;
11603 // something needs software processing, do it for real...
11604 // we only directly handle interleaved array data in this case...
11605 rsurface.batchgeneratedvertex = true;
11607 // now copy the vertex data into a combined array and make an index array
11608 // (this is what Quake3 does all the time)
11609 //if (gaps || rsurface.batchfirstvertex)
11611 rsurface.batchvertexposition = NULL;
11612 rsurface.batchvertexpositionbuffer = NULL;
11613 rsurface.batchvertexmesh = NULL;
11614 rsurface.batchvertexmeshbuffer = NULL;
11615 rsurface.batchvertex3f = NULL;
11616 rsurface.batchvertex3f_vertexbuffer = NULL;
11617 rsurface.batchvertex3f_bufferoffset = 0;
11618 rsurface.batchsvector3f = NULL;
11619 rsurface.batchsvector3f_vertexbuffer = NULL;
11620 rsurface.batchsvector3f_bufferoffset = 0;
11621 rsurface.batchtvector3f = NULL;
11622 rsurface.batchtvector3f_vertexbuffer = NULL;
11623 rsurface.batchtvector3f_bufferoffset = 0;
11624 rsurface.batchnormal3f = NULL;
11625 rsurface.batchnormal3f_vertexbuffer = NULL;
11626 rsurface.batchnormal3f_bufferoffset = 0;
11627 rsurface.batchlightmapcolor4f = NULL;
11628 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11629 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11630 rsurface.batchtexcoordtexture2f = NULL;
11631 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11632 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11633 rsurface.batchtexcoordlightmap2f = NULL;
11634 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11635 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11636 rsurface.batchelement3i = rsurface.array_batchelement3i;
11637 rsurface.batchelement3i_indexbuffer = NULL;
11638 rsurface.batchelement3i_bufferoffset = 0;
11639 rsurface.batchelement3s = NULL;
11640 rsurface.batchelement3s_indexbuffer = NULL;
11641 rsurface.batchelement3s_bufferoffset = 0;
11642 // we'll only be setting up certain arrays as needed
11643 if (batchneed & BATCHNEED_VERTEXPOSITION)
11644 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11645 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11646 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11647 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11648 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11649 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11650 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11651 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11653 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11654 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11656 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11657 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11658 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11659 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11660 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11661 rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11664 for (i = 0;i < texturenumsurfaces;i++)
11666 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11667 surfacenumvertices = texturesurfacelist[i]->num_vertices;
11668 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11669 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11670 // copy only the data requested
11671 if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11672 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11673 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11674 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11675 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11677 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11678 memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11679 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11680 memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11681 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11683 memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11684 memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11686 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11687 memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11688 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11689 memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11690 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11691 memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11693 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11694 numvertices += surfacenumvertices;
11695 numtriangles += surfacenumtriangles;
11698 // generate a 16bit index array as well if possible
11699 // (in general, dynamic batches fit)
11700 if (numvertices <= 65536)
11702 rsurface.batchelement3s = rsurface.array_batchelement3s;
11703 for (i = 0;i < numtriangles*3;i++)
11704 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11707 // since we've copied everything, the batch now starts at 0
11708 rsurface.batchfirstvertex = 0;
11709 rsurface.batchnumvertices = numvertices;
11710 rsurface.batchfirsttriangle = 0;
11711 rsurface.batchnumtriangles = numtriangles;
11714 // q1bsp surfaces rendered in vertex color mode have to have colors
11715 // calculated based on lightstyles
11716 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11718 // generate color arrays for the surfaces in this list
11722 const int *offsets;
11723 const unsigned char *lm;
11725 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11726 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11727 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11728 for (i = 0;i < texturenumsurfaces;i++)
11730 surface = texturesurfacelist[i];
11731 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11732 surfacenumvertices = surface->num_vertices;
11733 if (surface->lightmapinfo->samples)
11735 for (j = 0;j < surfacenumvertices;j++)
11737 lm = surface->lightmapinfo->samples + offsets[j];
11738 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11739 VectorScale(lm, scale, c);
11740 if (surface->lightmapinfo->styles[1] != 255)
11742 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11744 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11745 VectorMA(c, scale, lm, c);
11746 if (surface->lightmapinfo->styles[2] != 255)
11749 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11750 VectorMA(c, scale, lm, c);
11751 if (surface->lightmapinfo->styles[3] != 255)
11754 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11755 VectorMA(c, scale, lm, c);
11762 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);
11768 for (j = 0;j < surfacenumvertices;j++)
11770 Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11777 // if vertices are deformed (sprite flares and things in maps, possibly
11778 // water waves, bulges and other deformations), modify the copied vertices
11780 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11782 switch (deform->deform)
11785 case Q3DEFORM_PROJECTIONSHADOW:
11786 case Q3DEFORM_TEXT0:
11787 case Q3DEFORM_TEXT1:
11788 case Q3DEFORM_TEXT2:
11789 case Q3DEFORM_TEXT3:
11790 case Q3DEFORM_TEXT4:
11791 case Q3DEFORM_TEXT5:
11792 case Q3DEFORM_TEXT6:
11793 case Q3DEFORM_TEXT7:
11794 case Q3DEFORM_NONE:
11796 case Q3DEFORM_AUTOSPRITE:
11797 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11798 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11799 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11800 VectorNormalize(newforward);
11801 VectorNormalize(newright);
11802 VectorNormalize(newup);
11803 // a single autosprite surface can contain multiple sprites...
11804 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11806 VectorClear(center);
11807 for (i = 0;i < 4;i++)
11808 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11809 VectorScale(center, 0.25f, center);
11810 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11811 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11812 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11813 for (i = 0;i < 4;i++)
11815 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11816 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11819 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11820 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11821 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);
11822 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11823 rsurface.batchvertex3f_vertexbuffer = NULL;
11824 rsurface.batchvertex3f_bufferoffset = 0;
11825 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11826 rsurface.batchsvector3f_vertexbuffer = NULL;
11827 rsurface.batchsvector3f_bufferoffset = 0;
11828 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11829 rsurface.batchtvector3f_vertexbuffer = NULL;
11830 rsurface.batchtvector3f_bufferoffset = 0;
11831 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11832 rsurface.batchnormal3f_vertexbuffer = NULL;
11833 rsurface.batchnormal3f_bufferoffset = 0;
11835 case Q3DEFORM_AUTOSPRITE2:
11836 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11837 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11838 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11839 VectorNormalize(newforward);
11840 VectorNormalize(newright);
11841 VectorNormalize(newup);
11843 const float *v1, *v2;
11853 memset(shortest, 0, sizeof(shortest));
11854 // a single autosprite surface can contain multiple sprites...
11855 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11857 VectorClear(center);
11858 for (i = 0;i < 4;i++)
11859 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11860 VectorScale(center, 0.25f, center);
11861 // find the two shortest edges, then use them to define the
11862 // axis vectors for rotating around the central axis
11863 for (i = 0;i < 6;i++)
11865 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11866 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11867 l = VectorDistance2(v1, v2);
11868 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11869 if (v1[2] != v2[2])
11870 l += (1.0f / 1024.0f);
11871 if (shortest[0].length2 > l || i == 0)
11873 shortest[1] = shortest[0];
11874 shortest[0].length2 = l;
11875 shortest[0].v1 = v1;
11876 shortest[0].v2 = v2;
11878 else if (shortest[1].length2 > l || i == 1)
11880 shortest[1].length2 = l;
11881 shortest[1].v1 = v1;
11882 shortest[1].v2 = v2;
11885 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11886 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11887 // this calculates the right vector from the shortest edge
11888 // and the up vector from the edge midpoints
11889 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11890 VectorNormalize(right);
11891 VectorSubtract(end, start, up);
11892 VectorNormalize(up);
11893 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11894 VectorSubtract(rsurface.localvieworigin, center, forward);
11895 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11896 VectorNegate(forward, forward);
11897 VectorReflect(forward, 0, up, forward);
11898 VectorNormalize(forward);
11899 CrossProduct(up, forward, newright);
11900 VectorNormalize(newright);
11901 // rotate the quad around the up axis vector, this is made
11902 // especially easy by the fact we know the quad is flat,
11903 // so we only have to subtract the center position and
11904 // measure distance along the right vector, and then
11905 // multiply that by the newright vector and add back the
11907 // we also need to subtract the old position to undo the
11908 // displacement from the center, which we do with a
11909 // DotProduct, the subtraction/addition of center is also
11910 // optimized into DotProducts here
11911 l = DotProduct(right, center);
11912 for (i = 0;i < 4;i++)
11914 v1 = rsurface.batchvertex3f + 3*(j+i);
11915 f = DotProduct(right, v1) - l;
11916 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11920 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11921 rsurface.batchvertex3f_vertexbuffer = NULL;
11922 rsurface.batchvertex3f_bufferoffset = 0;
11923 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11925 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11926 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11927 rsurface.batchnormal3f_vertexbuffer = NULL;
11928 rsurface.batchnormal3f_bufferoffset = 0;
11930 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11932 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);
11933 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11934 rsurface.batchsvector3f_vertexbuffer = NULL;
11935 rsurface.batchsvector3f_bufferoffset = 0;
11936 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11937 rsurface.batchtvector3f_vertexbuffer = NULL;
11938 rsurface.batchtvector3f_bufferoffset = 0;
11941 case Q3DEFORM_NORMAL:
11942 // deform the normals to make reflections wavey
11943 for (j = 0;j < rsurface.batchnumvertices;j++)
11946 float *normal = rsurface.array_batchnormal3f + 3*j;
11947 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11948 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11949 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]);
11950 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]);
11951 VectorNormalize(normal);
11953 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11954 rsurface.batchnormal3f_vertexbuffer = NULL;
11955 rsurface.batchnormal3f_bufferoffset = 0;
11956 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11958 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11959 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11960 rsurface.batchsvector3f_vertexbuffer = NULL;
11961 rsurface.batchsvector3f_bufferoffset = 0;
11962 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11963 rsurface.batchtvector3f_vertexbuffer = NULL;
11964 rsurface.batchtvector3f_bufferoffset = 0;
11967 case Q3DEFORM_WAVE:
11968 // deform vertex array to make wavey water and flags and such
11969 waveparms[0] = deform->waveparms[0];
11970 waveparms[1] = deform->waveparms[1];
11971 waveparms[2] = deform->waveparms[2];
11972 waveparms[3] = deform->waveparms[3];
11973 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11974 break; // if wavefunc is a nop, don't make a dynamic vertex array
11975 // this is how a divisor of vertex influence on deformation
11976 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11977 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11978 for (j = 0;j < rsurface.batchnumvertices;j++)
11980 // if the wavefunc depends on time, evaluate it per-vertex
11983 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11984 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11986 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11988 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11989 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11990 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11991 rsurface.batchvertex3f_vertexbuffer = NULL;
11992 rsurface.batchvertex3f_bufferoffset = 0;
11993 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11994 rsurface.batchnormal3f_vertexbuffer = NULL;
11995 rsurface.batchnormal3f_bufferoffset = 0;
11996 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11998 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);
11999 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12000 rsurface.batchsvector3f_vertexbuffer = NULL;
12001 rsurface.batchsvector3f_bufferoffset = 0;
12002 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12003 rsurface.batchtvector3f_vertexbuffer = NULL;
12004 rsurface.batchtvector3f_bufferoffset = 0;
12007 case Q3DEFORM_BULGE:
12008 // deform vertex array to make the surface have moving bulges
12009 for (j = 0;j < rsurface.batchnumvertices;j++)
12011 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12012 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12014 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12015 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12016 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12017 rsurface.batchvertex3f_vertexbuffer = NULL;
12018 rsurface.batchvertex3f_bufferoffset = 0;
12019 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12020 rsurface.batchnormal3f_vertexbuffer = NULL;
12021 rsurface.batchnormal3f_bufferoffset = 0;
12022 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12024 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);
12025 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12026 rsurface.batchsvector3f_vertexbuffer = NULL;
12027 rsurface.batchsvector3f_bufferoffset = 0;
12028 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12029 rsurface.batchtvector3f_vertexbuffer = NULL;
12030 rsurface.batchtvector3f_bufferoffset = 0;
12033 case Q3DEFORM_MOVE:
12034 // deform vertex array
12035 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12036 break; // if wavefunc is a nop, don't make a dynamic vertex array
12037 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12038 VectorScale(deform->parms, scale, waveparms);
12039 for (j = 0;j < rsurface.batchnumvertices;j++)
12040 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12041 rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12042 rsurface.batchvertex3f_vertexbuffer = NULL;
12043 rsurface.batchvertex3f_bufferoffset = 0;
12048 // generate texcoords based on the chosen texcoord source
12049 switch(rsurface.texture->tcgen.tcgen)
12052 case Q3TCGEN_TEXTURE:
12054 case Q3TCGEN_LIGHTMAP:
12055 if (rsurface.batchtexcoordlightmap2f)
12056 memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12057 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12058 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12059 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12061 case Q3TCGEN_VECTOR:
12062 for (j = 0;j < rsurface.batchnumvertices;j++)
12064 rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12065 rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12067 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12068 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12069 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12071 case Q3TCGEN_ENVIRONMENT:
12072 // make environment reflections using a spheremap
12073 for (j = 0;j < rsurface.batchnumvertices;j++)
12075 // identical to Q3A's method, but executed in worldspace so
12076 // carried models can be shiny too
12078 float viewer[3], d, reflected[3], worldreflected[3];
12080 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12081 // VectorNormalize(viewer);
12083 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12085 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12086 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12087 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12088 // note: this is proportinal to viewer, so we can normalize later
12090 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12091 VectorNormalize(worldreflected);
12093 // note: this sphere map only uses world x and z!
12094 // so positive and negative y will LOOK THE SAME.
12095 rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12096 rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12098 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12099 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12100 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12103 // the only tcmod that needs software vertex processing is turbulent, so
12104 // check for it here and apply the changes if needed
12105 // and we only support that as the first one
12106 // (handling a mixture of turbulent and other tcmods would be problematic
12107 // without punting it entirely to a software path)
12108 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12110 amplitude = rsurface.texture->tcmods[0].parms[1];
12111 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12112 for (j = 0;j < rsurface.batchnumvertices;j++)
12114 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);
12115 rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12117 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12118 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12119 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12122 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12124 // convert the modified arrays to vertex structs
12125 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12126 rsurface.batchvertexmeshbuffer = NULL;
12127 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12128 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12129 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12130 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12131 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12132 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12133 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12135 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12137 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12138 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12141 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12142 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12143 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12144 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12145 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12146 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12147 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12148 for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12149 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12152 if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12154 // convert the modified arrays to vertex structs
12155 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12156 rsurface.batchvertexpositionbuffer = NULL;
12157 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12158 memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12160 for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12161 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12165 void RSurf_DrawBatch(void)
12167 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);
12170 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12172 // pick the closest matching water plane
12173 int planeindex, vertexindex, bestplaneindex = -1;
12177 r_waterstate_waterplane_t *p;
12179 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12181 if(p->camera_entity != rsurface.texture->camera_entity)
12184 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12185 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12187 Matrix4x4_Transform(&rsurface.matrix, v, vert);
12188 d += fabs(PlaneDiff(vert, &p->plane));
12190 if (bestd > d || bestplaneindex < 0)
12193 bestplaneindex = planeindex;
12196 return bestplaneindex;
12199 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12202 for (i = 0;i < rsurface.batchnumvertices;i++)
12203 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12204 rsurface.passcolor4f = rsurface.array_passcolor4f;
12205 rsurface.passcolor4f_vertexbuffer = 0;
12206 rsurface.passcolor4f_bufferoffset = 0;
12209 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12216 if (rsurface.passcolor4f)
12218 // generate color arrays
12219 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)
12221 f = RSurf_FogVertex(v);
12230 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12232 f = RSurf_FogVertex(v);
12239 rsurface.passcolor4f = rsurface.array_passcolor4f;
12240 rsurface.passcolor4f_vertexbuffer = 0;
12241 rsurface.passcolor4f_bufferoffset = 0;
12244 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12251 if (!rsurface.passcolor4f)
12253 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)
12255 f = RSurf_FogVertex(v);
12256 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12257 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12258 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12261 rsurface.passcolor4f = rsurface.array_passcolor4f;
12262 rsurface.passcolor4f_vertexbuffer = 0;
12263 rsurface.passcolor4f_bufferoffset = 0;
12266 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12271 if (!rsurface.passcolor4f)
12273 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12280 rsurface.passcolor4f = rsurface.array_passcolor4f;
12281 rsurface.passcolor4f_vertexbuffer = 0;
12282 rsurface.passcolor4f_bufferoffset = 0;
12285 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12290 if (!rsurface.passcolor4f)
12292 for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12294 c2[0] = c[0] + r_refdef.scene.ambient;
12295 c2[1] = c[1] + r_refdef.scene.ambient;
12296 c2[2] = c[2] + r_refdef.scene.ambient;
12299 rsurface.passcolor4f = rsurface.array_passcolor4f;
12300 rsurface.passcolor4f_vertexbuffer = 0;
12301 rsurface.passcolor4f_bufferoffset = 0;
12304 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12307 rsurface.passcolor4f = NULL;
12308 rsurface.passcolor4f_vertexbuffer = 0;
12309 rsurface.passcolor4f_bufferoffset = 0;
12310 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12311 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12312 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12313 GL_Color(r, g, b, a);
12314 R_Mesh_TexBind(0, rsurface.lightmaptexture);
12318 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12320 // TODO: optimize applyfog && applycolor case
12321 // just apply fog if necessary, and tint the fog color array if necessary
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);
12332 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12335 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12336 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12337 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12338 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12339 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12340 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12341 GL_Color(r, g, b, a);
12345 static void RSurf_DrawBatch_GL11_ClampColor(void)
12350 if (!rsurface.passcolor4f)
12352 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12354 c2[0] = bound(0.0f, c1[0], 1.0f);
12355 c2[1] = bound(0.0f, c1[1], 1.0f);
12356 c2[2] = bound(0.0f, c1[2], 1.0f);
12357 c2[3] = bound(0.0f, c1[3], 1.0f);
12361 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12371 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)
12373 f = -DotProduct(r_refdef.view.forward, n);
12375 f = f * 0.85 + 0.15; // work around so stuff won't get black
12376 f *= r_refdef.lightmapintensity;
12377 Vector4Set(c, f, f, f, 1);
12380 rsurface.passcolor4f = rsurface.array_passcolor4f;
12381 rsurface.passcolor4f_vertexbuffer = 0;
12382 rsurface.passcolor4f_bufferoffset = 0;
12385 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12387 RSurf_DrawBatch_GL11_ApplyFakeLight();
12388 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12389 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12390 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12391 GL_Color(r, g, b, a);
12395 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12403 vec3_t ambientcolor;
12404 vec3_t diffusecolor;
12408 VectorCopy(rsurface.modellight_lightdir, lightdir);
12409 f = 0.5f * r_refdef.lightmapintensity;
12410 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12411 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12412 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12413 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12414 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12415 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12417 if (VectorLength2(diffusecolor) > 0)
12419 // q3-style directional shading
12420 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)
12422 if ((f = DotProduct(n, lightdir)) > 0)
12423 VectorMA(ambientcolor, f, diffusecolor, c);
12425 VectorCopy(ambientcolor, c);
12432 rsurface.passcolor4f = rsurface.array_passcolor4f;
12433 rsurface.passcolor4f_vertexbuffer = 0;
12434 rsurface.passcolor4f_bufferoffset = 0;
12435 *applycolor = false;
12439 *r = ambientcolor[0];
12440 *g = ambientcolor[1];
12441 *b = ambientcolor[2];
12442 rsurface.passcolor4f = NULL;
12443 rsurface.passcolor4f_vertexbuffer = 0;
12444 rsurface.passcolor4f_bufferoffset = 0;
12448 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12450 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12451 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
12452 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12453 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12454 GL_Color(r, g, b, a);
12458 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12464 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12466 f = 1 - RSurf_FogVertex(v);
12474 void RSurf_SetupDepthAndCulling(void)
12476 // submodels are biased to avoid z-fighting with world surfaces that they
12477 // may be exactly overlapping (avoids z-fighting artifacts on certain
12478 // doors and things in Quake maps)
12479 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12480 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12481 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12482 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12485 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12487 // transparent sky would be ridiculous
12488 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12490 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12491 skyrenderlater = true;
12492 RSurf_SetupDepthAndCulling();
12493 GL_DepthMask(true);
12494 // LordHavoc: HalfLife maps have freaky skypolys so don't use
12495 // skymasking on them, and Quake3 never did sky masking (unlike
12496 // software Quake and software Quake2), so disable the sky masking
12497 // in Quake3 maps as it causes problems with q3map2 sky tricks,
12498 // and skymasking also looks very bad when noclipping outside the
12499 // level, so don't use it then either.
12500 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12502 R_Mesh_ResetTextureState();
12503 if (skyrendermasked)
12505 R_SetupShader_DepthOrShadow();
12506 // depth-only (masking)
12507 GL_ColorMask(0,0,0,0);
12508 // just to make sure that braindead drivers don't draw
12509 // anything despite that colormask...
12510 GL_BlendFunc(GL_ZERO, GL_ONE);
12511 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12512 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12516 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12518 GL_BlendFunc(GL_ONE, GL_ZERO);
12519 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12520 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12521 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12524 if (skyrendermasked)
12525 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12527 R_Mesh_ResetTextureState();
12528 GL_Color(1, 1, 1, 1);
12531 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12532 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12533 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12535 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12539 // render screenspace normalmap to texture
12540 GL_DepthMask(true);
12541 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12546 // bind lightmap texture
12548 // water/refraction/reflection/camera surfaces have to be handled specially
12549 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12551 int start, end, startplaneindex;
12552 for (start = 0;start < texturenumsurfaces;start = end)
12554 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12555 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12557 // now that we have a batch using the same planeindex, render it
12558 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12560 // render water or distortion background
12561 GL_DepthMask(true);
12562 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));
12564 // blend surface on top
12565 GL_DepthMask(false);
12566 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12569 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12571 // render surface with reflection texture as input
12572 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12573 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));
12580 // render surface batch normally
12581 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12582 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12586 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12588 // OpenGL 1.3 path - anything not completely ancient
12589 qboolean applycolor;
12592 const texturelayer_t *layer;
12593 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);
12594 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12596 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12599 int layertexrgbscale;
12600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12602 if (layerindex == 0)
12603 GL_AlphaTest(true);
12606 GL_AlphaTest(false);
12607 GL_DepthFunc(GL_EQUAL);
12610 GL_DepthMask(layer->depthmask && writedepth);
12611 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12612 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12614 layertexrgbscale = 4;
12615 VectorScale(layer->color, 0.25f, layercolor);
12617 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12619 layertexrgbscale = 2;
12620 VectorScale(layer->color, 0.5f, layercolor);
12624 layertexrgbscale = 1;
12625 VectorScale(layer->color, 1.0f, layercolor);
12627 layercolor[3] = layer->color[3];
12628 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12629 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12630 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12631 switch (layer->type)
12633 case TEXTURELAYERTYPE_LITTEXTURE:
12634 // single-pass lightmapped texture with 2x rgbscale
12635 R_Mesh_TexBind(0, r_texture_white);
12636 R_Mesh_TexMatrix(0, NULL);
12637 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12638 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12639 R_Mesh_TexBind(1, layer->texture);
12640 R_Mesh_TexMatrix(1, &layer->texmatrix);
12641 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12642 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12643 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12644 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12645 else if (FAKELIGHT_ENABLED)
12646 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12647 else if (rsurface.uselightmaptexture)
12648 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12650 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12652 case TEXTURELAYERTYPE_TEXTURE:
12653 // singletexture unlit texture with transparency support
12654 R_Mesh_TexBind(0, layer->texture);
12655 R_Mesh_TexMatrix(0, &layer->texmatrix);
12656 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12657 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12658 R_Mesh_TexBind(1, 0);
12659 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12660 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12662 case TEXTURELAYERTYPE_FOG:
12663 // singletexture fogging
12664 if (layer->texture)
12666 R_Mesh_TexBind(0, layer->texture);
12667 R_Mesh_TexMatrix(0, &layer->texmatrix);
12668 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12669 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12673 R_Mesh_TexBind(0, 0);
12674 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12676 R_Mesh_TexBind(1, 0);
12677 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12678 // generate a color array for the fog pass
12679 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12680 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12684 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12687 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12689 GL_DepthFunc(GL_LEQUAL);
12690 GL_AlphaTest(false);
12694 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12696 // OpenGL 1.1 - crusty old voodoo path
12699 const texturelayer_t *layer;
12700 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);
12701 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12703 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12705 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12707 if (layerindex == 0)
12708 GL_AlphaTest(true);
12711 GL_AlphaTest(false);
12712 GL_DepthFunc(GL_EQUAL);
12715 GL_DepthMask(layer->depthmask && writedepth);
12716 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12717 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12718 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12719 switch (layer->type)
12721 case TEXTURELAYERTYPE_LITTEXTURE:
12722 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12724 // two-pass lit texture with 2x rgbscale
12725 // first the lightmap pass
12726 R_Mesh_TexBind(0, r_texture_white);
12727 R_Mesh_TexMatrix(0, NULL);
12728 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12729 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12730 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12731 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12732 else if (FAKELIGHT_ENABLED)
12733 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12734 else if (rsurface.uselightmaptexture)
12735 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12737 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12738 // then apply the texture to it
12739 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12740 R_Mesh_TexBind(0, layer->texture);
12741 R_Mesh_TexMatrix(0, &layer->texmatrix);
12742 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12743 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12744 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);
12748 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12749 R_Mesh_TexBind(0, layer->texture);
12750 R_Mesh_TexMatrix(0, &layer->texmatrix);
12751 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12752 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12753 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12754 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);
12756 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);
12759 case TEXTURELAYERTYPE_TEXTURE:
12760 // singletexture unlit texture with transparency support
12761 R_Mesh_TexBind(0, layer->texture);
12762 R_Mesh_TexMatrix(0, &layer->texmatrix);
12763 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12764 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12765 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);
12767 case TEXTURELAYERTYPE_FOG:
12768 // singletexture fogging
12769 if (layer->texture)
12771 R_Mesh_TexBind(0, layer->texture);
12772 R_Mesh_TexMatrix(0, &layer->texmatrix);
12773 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12774 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12778 R_Mesh_TexBind(0, 0);
12779 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12781 // generate a color array for the fog pass
12782 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12783 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12787 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12790 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12792 GL_DepthFunc(GL_LEQUAL);
12793 GL_AlphaTest(false);
12797 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12801 r_vertexgeneric_t *batchvertex;
12804 GL_AlphaTest(false);
12805 R_Mesh_ResetTextureState();
12806 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12808 if(rsurface.texture && rsurface.texture->currentskinframe)
12810 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12811 c[3] *= rsurface.texture->currentalpha;
12821 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12823 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12824 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12825 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12828 // brighten it up (as texture value 127 means "unlit")
12829 c[0] *= 2 * r_refdef.view.colorscale;
12830 c[1] *= 2 * r_refdef.view.colorscale;
12831 c[2] *= 2 * r_refdef.view.colorscale;
12833 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12834 c[3] *= r_wateralpha.value;
12836 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12838 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12839 GL_DepthMask(false);
12841 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12843 GL_BlendFunc(GL_ONE, GL_ONE);
12844 GL_DepthMask(false);
12846 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12848 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12849 GL_DepthMask(false);
12851 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12853 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12854 GL_DepthMask(false);
12858 GL_BlendFunc(GL_ONE, GL_ZERO);
12859 GL_DepthMask(writedepth);
12862 if (r_showsurfaces.integer == 3)
12864 rsurface.passcolor4f = NULL;
12866 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12868 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12870 rsurface.passcolor4f = NULL;
12871 rsurface.passcolor4f_vertexbuffer = 0;
12872 rsurface.passcolor4f_bufferoffset = 0;
12874 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12876 qboolean applycolor = true;
12879 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12881 r_refdef.lightmapintensity = 1;
12882 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12883 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12885 else if (FAKELIGHT_ENABLED)
12887 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12889 r_refdef.lightmapintensity = r_fakelight_intensity.value;
12890 RSurf_DrawBatch_GL11_ApplyFakeLight();
12891 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12895 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12897 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12898 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12899 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12902 if(!rsurface.passcolor4f)
12903 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12905 RSurf_DrawBatch_GL11_ApplyAmbient();
12906 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12907 if(r_refdef.fogenabled)
12908 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12909 RSurf_DrawBatch_GL11_ClampColor();
12911 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12912 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12915 else if (!r_refdef.view.showdebug)
12917 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12918 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12919 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12921 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12922 Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12924 R_Mesh_PrepareVertices_Generic_Unlock();
12927 else if (r_showsurfaces.integer == 4)
12929 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12930 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12931 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12933 unsigned char c = vi << 3;
12934 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12935 Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12937 R_Mesh_PrepareVertices_Generic_Unlock();
12940 else if (r_showsurfaces.integer == 2)
12943 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12944 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12945 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12947 unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12948 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12949 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12950 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12951 Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12952 Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12953 Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12955 R_Mesh_PrepareVertices_Generic_Unlock();
12956 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12960 int texturesurfaceindex;
12962 const msurface_t *surface;
12963 unsigned char surfacecolor4ub[4];
12964 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12965 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12969 surface = texturesurfacelist[texturesurfaceindex];
12970 k = (int)(((size_t)surface) / sizeof(msurface_t));
12971 Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12972 for (j = 0;j < surface->num_vertices;j++)
12974 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12975 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12979 R_Mesh_PrepareVertices_Generic_Unlock();
12984 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12987 RSurf_SetupDepthAndCulling();
12988 if (r_showsurfaces.integer)
12990 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12993 switch (vid.renderpath)
12995 case RENDERPATH_GL20:
12996 case RENDERPATH_CGGL:
12997 case RENDERPATH_D3D9:
12998 case RENDERPATH_D3D10:
12999 case RENDERPATH_D3D11:
13000 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13002 case RENDERPATH_GL13:
13003 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13005 case RENDERPATH_GL11:
13006 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13012 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13015 RSurf_SetupDepthAndCulling();
13016 if (r_showsurfaces.integer)
13018 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13021 switch (vid.renderpath)
13023 case RENDERPATH_GL20:
13024 case RENDERPATH_CGGL:
13025 case RENDERPATH_D3D9:
13026 case RENDERPATH_D3D10:
13027 case RENDERPATH_D3D11:
13028 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13030 case RENDERPATH_GL13:
13031 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13033 case RENDERPATH_GL11:
13034 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13040 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13043 int texturenumsurfaces, endsurface;
13044 texture_t *texture;
13045 const msurface_t *surface;
13046 #define MAXBATCH_TRANSPARENTSURFACES 256
13047 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13049 // if the model is static it doesn't matter what value we give for
13050 // wantnormals and wanttangents, so this logic uses only rules applicable
13051 // to a model, knowing that they are meaningless otherwise
13052 if (ent == r_refdef.scene.worldentity)
13053 RSurf_ActiveWorldEntity();
13054 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13055 RSurf_ActiveModelEntity(ent, false, false, false);
13058 switch (vid.renderpath)
13060 case RENDERPATH_GL20:
13061 case RENDERPATH_CGGL:
13062 case RENDERPATH_D3D9:
13063 case RENDERPATH_D3D10:
13064 case RENDERPATH_D3D11:
13065 RSurf_ActiveModelEntity(ent, true, true, false);
13067 case RENDERPATH_GL13:
13068 case RENDERPATH_GL11:
13069 RSurf_ActiveModelEntity(ent, true, false, false);
13074 if (r_transparentdepthmasking.integer)
13076 qboolean setup = false;
13077 for (i = 0;i < numsurfaces;i = j)
13080 surface = rsurface.modelsurfaces + surfacelist[i];
13081 texture = surface->texture;
13082 rsurface.texture = R_GetCurrentTexture(texture);
13083 rsurface.lightmaptexture = NULL;
13084 rsurface.deluxemaptexture = NULL;
13085 rsurface.uselightmaptexture = false;
13086 // scan ahead until we find a different texture
13087 endsurface = min(i + 1024, numsurfaces);
13088 texturenumsurfaces = 0;
13089 texturesurfacelist[texturenumsurfaces++] = surface;
13090 for (;j < endsurface;j++)
13092 surface = rsurface.modelsurfaces + surfacelist[j];
13093 if (texture != surface->texture)
13095 texturesurfacelist[texturenumsurfaces++] = surface;
13097 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13099 // render the range of surfaces as depth
13103 GL_ColorMask(0,0,0,0);
13105 GL_DepthTest(true);
13106 GL_BlendFunc(GL_ONE, GL_ZERO);
13107 GL_DepthMask(true);
13108 GL_AlphaTest(false);
13109 R_Mesh_ResetTextureState();
13110 R_SetupShader_DepthOrShadow();
13112 RSurf_SetupDepthAndCulling();
13113 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13114 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13118 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13121 for (i = 0;i < numsurfaces;i = j)
13124 surface = rsurface.modelsurfaces + surfacelist[i];
13125 texture = surface->texture;
13126 rsurface.texture = R_GetCurrentTexture(texture);
13127 // scan ahead until we find a different texture
13128 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13129 texturenumsurfaces = 0;
13130 texturesurfacelist[texturenumsurfaces++] = surface;
13131 if(FAKELIGHT_ENABLED)
13133 rsurface.lightmaptexture = NULL;
13134 rsurface.deluxemaptexture = NULL;
13135 rsurface.uselightmaptexture = false;
13136 for (;j < endsurface;j++)
13138 surface = rsurface.modelsurfaces + surfacelist[j];
13139 if (texture != surface->texture)
13141 texturesurfacelist[texturenumsurfaces++] = surface;
13146 rsurface.lightmaptexture = surface->lightmaptexture;
13147 rsurface.deluxemaptexture = surface->deluxemaptexture;
13148 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13149 for (;j < endsurface;j++)
13151 surface = rsurface.modelsurfaces + surfacelist[j];
13152 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13154 texturesurfacelist[texturenumsurfaces++] = surface;
13157 // render the range of surfaces
13158 if (ent == r_refdef.scene.worldentity)
13159 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13161 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13163 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13164 GL_AlphaTest(false);
13167 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13169 // transparent surfaces get pushed off into the transparent queue
13170 int surfacelistindex;
13171 const msurface_t *surface;
13172 vec3_t tempcenter, center;
13173 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13175 surface = texturesurfacelist[surfacelistindex];
13176 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13177 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13178 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13179 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13180 if (queueentity->transparent_offset) // transparent offset
13182 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13183 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13184 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13186 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13190 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13192 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13194 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13196 RSurf_SetupDepthAndCulling();
13197 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13198 R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13202 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13204 const entity_render_t *queueentity = r_refdef.scene.worldentity;
13207 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13210 if (!rsurface.texture->currentnumlayers)
13212 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13213 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13215 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13217 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13218 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13219 else if (!rsurface.texture->currentnumlayers)
13221 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13223 // in the deferred case, transparent surfaces were queued during prepass
13224 if (!r_shadow_usingdeferredprepass)
13225 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13229 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13230 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13235 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13238 texture_t *texture;
13239 // break the surface list down into batches by texture and use of lightmapping
13240 for (i = 0;i < numsurfaces;i = j)
13243 // texture is the base texture pointer, rsurface.texture is the
13244 // current frame/skin the texture is directing us to use (for example
13245 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13246 // use skin 1 instead)
13247 texture = surfacelist[i]->texture;
13248 rsurface.texture = R_GetCurrentTexture(texture);
13249 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13251 // if this texture is not the kind we want, skip ahead to the next one
13252 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13256 if(FAKELIGHT_ENABLED || depthonly || prepass)
13258 rsurface.lightmaptexture = NULL;
13259 rsurface.deluxemaptexture = NULL;
13260 rsurface.uselightmaptexture = false;
13261 // simply scan ahead until we find a different texture or lightmap state
13262 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13267 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13268 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13269 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13270 // simply scan ahead until we find a different texture or lightmap state
13271 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13274 // render the range of surfaces
13275 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13279 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13283 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13286 if (!rsurface.texture->currentnumlayers)
13288 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13289 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13291 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13293 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13294 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13295 else if (!rsurface.texture->currentnumlayers)
13297 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13299 // in the deferred case, transparent surfaces were queued during prepass
13300 if (!r_shadow_usingdeferredprepass)
13301 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13305 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13306 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13311 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13314 texture_t *texture;
13315 // break the surface list down into batches by texture and use of lightmapping
13316 for (i = 0;i < numsurfaces;i = j)
13319 // texture is the base texture pointer, rsurface.texture is the
13320 // current frame/skin the texture is directing us to use (for example
13321 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13322 // use skin 1 instead)
13323 texture = surfacelist[i]->texture;
13324 rsurface.texture = R_GetCurrentTexture(texture);
13325 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13327 // if this texture is not the kind we want, skip ahead to the next one
13328 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13332 if(FAKELIGHT_ENABLED || depthonly || prepass)
13334 rsurface.lightmaptexture = NULL;
13335 rsurface.deluxemaptexture = NULL;
13336 rsurface.uselightmaptexture = false;
13337 // simply scan ahead until we find a different texture or lightmap state
13338 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13343 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13344 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13345 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13346 // simply scan ahead until we find a different texture or lightmap state
13347 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13350 // render the range of surfaces
13351 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13355 float locboxvertex3f[6*4*3] =
13357 1,0,1, 1,0,0, 1,1,0, 1,1,1,
13358 0,1,1, 0,1,0, 0,0,0, 0,0,1,
13359 1,1,1, 1,1,0, 0,1,0, 0,1,1,
13360 0,0,1, 0,0,0, 1,0,0, 1,0,1,
13361 0,0,1, 1,0,1, 1,1,1, 0,1,1,
13362 1,0,0, 0,0,0, 0,1,0, 1,1,0
13365 unsigned short locboxelements[6*2*3] =
13370 12,13,14, 12,14,15,
13371 16,17,18, 16,18,19,
13375 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13378 cl_locnode_t *loc = (cl_locnode_t *)ent;
13380 float vertex3f[6*4*3];
13382 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13383 GL_DepthMask(false);
13384 GL_DepthRange(0, 1);
13385 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13386 GL_DepthTest(true);
13387 GL_CullFace(GL_NONE);
13388 R_EntityMatrix(&identitymatrix);
13390 R_Mesh_ResetTextureState();
13392 i = surfacelist[0];
13393 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13394 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13395 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13396 surfacelist[0] < 0 ? 0.5f : 0.125f);
13398 if (VectorCompare(loc->mins, loc->maxs))
13400 VectorSet(size, 2, 2, 2);
13401 VectorMA(loc->mins, -0.5f, size, mins);
13405 VectorCopy(loc->mins, mins);
13406 VectorSubtract(loc->maxs, loc->mins, size);
13409 for (i = 0;i < 6*4*3;)
13410 for (j = 0;j < 3;j++, i++)
13411 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13413 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13414 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13415 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13418 void R_DrawLocs(void)
13421 cl_locnode_t *loc, *nearestloc;
13423 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13424 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13426 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13427 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13431 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13433 if (decalsystem->decals)
13434 Mem_Free(decalsystem->decals);
13435 memset(decalsystem, 0, sizeof(*decalsystem));
13438 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)
13441 tridecal_t *decals;
13444 // expand or initialize the system
13445 if (decalsystem->maxdecals <= decalsystem->numdecals)
13447 decalsystem_t old = *decalsystem;
13448 qboolean useshortelements;
13449 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13450 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13451 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)));
13452 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13453 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13454 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13455 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13456 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13457 if (decalsystem->numdecals)
13458 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13460 Mem_Free(old.decals);
13461 for (i = 0;i < decalsystem->maxdecals*3;i++)
13462 decalsystem->element3i[i] = i;
13463 if (useshortelements)
13464 for (i = 0;i < decalsystem->maxdecals*3;i++)
13465 decalsystem->element3s[i] = i;
13468 // grab a decal and search for another free slot for the next one
13469 decals = decalsystem->decals;
13470 decal = decalsystem->decals + (i = decalsystem->freedecal++);
13471 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13473 decalsystem->freedecal = i;
13474 if (decalsystem->numdecals <= i)
13475 decalsystem->numdecals = i + 1;
13477 // initialize the decal
13479 decal->triangleindex = triangleindex;
13480 decal->surfaceindex = surfaceindex;
13481 decal->decalsequence = decalsequence;
13482 decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13483 decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13484 decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13485 decal->color4ub[0][3] = 255;
13486 decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13487 decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13488 decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13489 decal->color4ub[1][3] = 255;
13490 decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13491 decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13492 decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13493 decal->color4ub[2][3] = 255;
13494 decal->vertex3f[0][0] = v0[0];
13495 decal->vertex3f[0][1] = v0[1];
13496 decal->vertex3f[0][2] = v0[2];
13497 decal->vertex3f[1][0] = v1[0];
13498 decal->vertex3f[1][1] = v1[1];
13499 decal->vertex3f[1][2] = v1[2];
13500 decal->vertex3f[2][0] = v2[0];
13501 decal->vertex3f[2][1] = v2[1];
13502 decal->vertex3f[2][2] = v2[2];
13503 decal->texcoord2f[0][0] = t0[0];
13504 decal->texcoord2f[0][1] = t0[1];
13505 decal->texcoord2f[1][0] = t1[0];
13506 decal->texcoord2f[1][1] = t1[1];
13507 decal->texcoord2f[2][0] = t2[0];
13508 decal->texcoord2f[2][1] = t2[1];
13511 extern cvar_t cl_decals_bias;
13512 extern cvar_t cl_decals_models;
13513 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13514 // baseparms, parms, temps
13515 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)
13520 const float *vertex3f;
13522 float points[2][9][3];
13529 e = rsurface.modelelement3i + 3*triangleindex;
13531 vertex3f = rsurface.modelvertex3f;
13533 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13535 index = 3*e[cornerindex];
13536 VectorCopy(vertex3f + index, v[cornerindex]);
13539 //TriangleNormal(v[0], v[1], v[2], normal);
13540 //if (DotProduct(normal, localnormal) < 0.0f)
13542 // clip by each of the box planes formed from the projection matrix
13543 // if anything survives, we emit the decal
13544 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]);
13547 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]);
13550 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]);
13553 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]);
13556 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]);
13559 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]);
13562 // some part of the triangle survived, so we have to accept it...
13565 // dynamic always uses the original triangle
13567 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13569 index = 3*e[cornerindex];
13570 VectorCopy(vertex3f + index, v[cornerindex]);
13573 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13575 // convert vertex positions to texcoords
13576 Matrix4x4_Transform(projection, v[cornerindex], temp);
13577 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13578 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13579 // calculate distance fade from the projection origin
13580 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13581 f = bound(0.0f, f, 1.0f);
13582 c[cornerindex][0] = r * f;
13583 c[cornerindex][1] = g * f;
13584 c[cornerindex][2] = b * f;
13585 c[cornerindex][3] = 1.0f;
13586 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13589 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);
13591 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13592 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);
13594 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)
13596 matrix4x4_t projection;
13597 decalsystem_t *decalsystem;
13600 const msurface_t *surface;
13601 const msurface_t *surfaces;
13602 const int *surfacelist;
13603 const texture_t *texture;
13605 int numsurfacelist;
13606 int surfacelistindex;
13609 float localorigin[3];
13610 float localnormal[3];
13611 float localmins[3];
13612 float localmaxs[3];
13615 float planes[6][4];
13618 int bih_triangles_count;
13619 int bih_triangles[256];
13620 int bih_surfaces[256];
13622 decalsystem = &ent->decalsystem;
13623 model = ent->model;
13624 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13626 R_DecalSystem_Reset(&ent->decalsystem);
13630 if (!model->brush.data_leafs && !cl_decals_models.integer)
13632 if (decalsystem->model)
13633 R_DecalSystem_Reset(decalsystem);
13637 if (decalsystem->model != model)
13638 R_DecalSystem_Reset(decalsystem);
13639 decalsystem->model = model;
13641 RSurf_ActiveModelEntity(ent, false, false, false);
13643 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13644 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13645 VectorNormalize(localnormal);
13646 localsize = worldsize*rsurface.inversematrixscale;
13647 localmins[0] = localorigin[0] - localsize;
13648 localmins[1] = localorigin[1] - localsize;
13649 localmins[2] = localorigin[2] - localsize;
13650 localmaxs[0] = localorigin[0] + localsize;
13651 localmaxs[1] = localorigin[1] + localsize;
13652 localmaxs[2] = localorigin[2] + localsize;
13654 //VectorCopy(localnormal, planes[4]);
13655 //VectorVectors(planes[4], planes[2], planes[0]);
13656 AnglesFromVectors(angles, localnormal, NULL, false);
13657 AngleVectors(angles, planes[0], planes[2], planes[4]);
13658 VectorNegate(planes[0], planes[1]);
13659 VectorNegate(planes[2], planes[3]);
13660 VectorNegate(planes[4], planes[5]);
13661 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13662 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13663 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13664 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13665 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13666 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13671 matrix4x4_t forwardprojection;
13672 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13673 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13678 float projectionvector[4][3];
13679 VectorScale(planes[0], ilocalsize, projectionvector[0]);
13680 VectorScale(planes[2], ilocalsize, projectionvector[1]);
13681 VectorScale(planes[4], ilocalsize, projectionvector[2]);
13682 projectionvector[0][0] = planes[0][0] * ilocalsize;
13683 projectionvector[0][1] = planes[1][0] * ilocalsize;
13684 projectionvector[0][2] = planes[2][0] * ilocalsize;
13685 projectionvector[1][0] = planes[0][1] * ilocalsize;
13686 projectionvector[1][1] = planes[1][1] * ilocalsize;
13687 projectionvector[1][2] = planes[2][1] * ilocalsize;
13688 projectionvector[2][0] = planes[0][2] * ilocalsize;
13689 projectionvector[2][1] = planes[1][2] * ilocalsize;
13690 projectionvector[2][2] = planes[2][2] * ilocalsize;
13691 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13692 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13693 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13694 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13698 dynamic = model->surfmesh.isanimated;
13699 numsurfacelist = model->nummodelsurfaces;
13700 surfacelist = model->sortedmodelsurfaces;
13701 surfaces = model->data_surfaces;
13704 bih_triangles_count = -1;
13707 if(model->render_bih.numleafs)
13708 bih = &model->render_bih;
13709 else if(model->collision_bih.numleafs)
13710 bih = &model->collision_bih;
13713 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13714 if(bih_triangles_count == 0)
13716 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13718 if(bih_triangles_count > 0)
13720 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13722 surfaceindex = bih_surfaces[triangleindex];
13723 surface = surfaces + surfaceindex;
13724 texture = surface->texture;
13725 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13727 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13729 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13734 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13736 surfaceindex = surfacelist[surfacelistindex];
13737 surface = surfaces + surfaceindex;
13738 // check cull box first because it rejects more than any other check
13739 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13741 // skip transparent surfaces
13742 texture = surface->texture;
13743 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13745 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13747 numtriangles = surface->num_triangles;
13748 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13749 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13754 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13755 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)
13757 int renderentityindex;
13758 float worldmins[3];
13759 float worldmaxs[3];
13760 entity_render_t *ent;
13762 if (!cl_decals_newsystem.integer)
13765 worldmins[0] = worldorigin[0] - worldsize;
13766 worldmins[1] = worldorigin[1] - worldsize;
13767 worldmins[2] = worldorigin[2] - worldsize;
13768 worldmaxs[0] = worldorigin[0] + worldsize;
13769 worldmaxs[1] = worldorigin[1] + worldsize;
13770 worldmaxs[2] = worldorigin[2] + worldsize;
13772 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13774 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13776 ent = r_refdef.scene.entities[renderentityindex];
13777 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13780 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13784 typedef struct r_decalsystem_splatqueue_s
13786 vec3_t worldorigin;
13787 vec3_t worldnormal;
13793 r_decalsystem_splatqueue_t;
13795 int r_decalsystem_numqueued = 0;
13796 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13798 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)
13800 r_decalsystem_splatqueue_t *queue;
13802 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13805 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13806 VectorCopy(worldorigin, queue->worldorigin);
13807 VectorCopy(worldnormal, queue->worldnormal);
13808 Vector4Set(queue->color, r, g, b, a);
13809 Vector4Set(queue->tcrange, s1, t1, s2, t2);
13810 queue->worldsize = worldsize;
13811 queue->decalsequence = cl.decalsequence++;
13814 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13817 r_decalsystem_splatqueue_t *queue;
13819 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13820 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);
13821 r_decalsystem_numqueued = 0;
13824 extern cvar_t cl_decals_max;
13825 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13828 decalsystem_t *decalsystem = &ent->decalsystem;
13835 if (!decalsystem->numdecals)
13838 if (r_showsurfaces.integer)
13841 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13843 R_DecalSystem_Reset(decalsystem);
13847 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13848 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13850 if (decalsystem->lastupdatetime)
13851 frametime = (cl.time - decalsystem->lastupdatetime);
13854 decalsystem->lastupdatetime = cl.time;
13855 decal = decalsystem->decals;
13856 numdecals = decalsystem->numdecals;
13858 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13860 if (decal->color4ub[0][3])
13862 decal->lived += frametime;
13863 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13865 memset(decal, 0, sizeof(*decal));
13866 if (decalsystem->freedecal > i)
13867 decalsystem->freedecal = i;
13871 decal = decalsystem->decals;
13872 while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13875 // collapse the array by shuffling the tail decals into the gaps
13878 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13879 decalsystem->freedecal++;
13880 if (decalsystem->freedecal == numdecals)
13882 decal[decalsystem->freedecal] = decal[--numdecals];
13885 decalsystem->numdecals = numdecals;
13887 if (numdecals <= 0)
13889 // if there are no decals left, reset decalsystem
13890 R_DecalSystem_Reset(decalsystem);
13894 extern skinframe_t *decalskinframe;
13895 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13898 decalsystem_t *decalsystem = &ent->decalsystem;
13907 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13910 numdecals = decalsystem->numdecals;
13914 if (r_showsurfaces.integer)
13917 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13919 R_DecalSystem_Reset(decalsystem);
13923 // if the model is static it doesn't matter what value we give for
13924 // wantnormals and wanttangents, so this logic uses only rules applicable
13925 // to a model, knowing that they are meaningless otherwise
13926 if (ent == r_refdef.scene.worldentity)
13927 RSurf_ActiveWorldEntity();
13929 RSurf_ActiveModelEntity(ent, false, false, false);
13931 decalsystem->lastupdatetime = cl.time;
13932 decal = decalsystem->decals;
13934 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13936 // update vertex positions for animated models
13937 v3f = decalsystem->vertex3f;
13938 c4f = decalsystem->color4f;
13939 t2f = decalsystem->texcoord2f;
13940 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13942 if (!decal->color4ub[0][3])
13945 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13948 // update color values for fading decals
13949 if (decal->lived >= cl_decals_time.value)
13951 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13952 alpha *= (1.0f/255.0f);
13955 alpha = 1.0f/255.0f;
13957 c4f[ 0] = decal->color4ub[0][0] * alpha;
13958 c4f[ 1] = decal->color4ub[0][1] * alpha;
13959 c4f[ 2] = decal->color4ub[0][2] * alpha;
13961 c4f[ 4] = decal->color4ub[1][0] * alpha;
13962 c4f[ 5] = decal->color4ub[1][1] * alpha;
13963 c4f[ 6] = decal->color4ub[1][2] * alpha;
13965 c4f[ 8] = decal->color4ub[2][0] * alpha;
13966 c4f[ 9] = decal->color4ub[2][1] * alpha;
13967 c4f[10] = decal->color4ub[2][2] * alpha;
13970 t2f[0] = decal->texcoord2f[0][0];
13971 t2f[1] = decal->texcoord2f[0][1];
13972 t2f[2] = decal->texcoord2f[1][0];
13973 t2f[3] = decal->texcoord2f[1][1];
13974 t2f[4] = decal->texcoord2f[2][0];
13975 t2f[5] = decal->texcoord2f[2][1];
13977 // update vertex positions for animated models
13978 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13980 e = rsurface.modelelement3i + 3*decal->triangleindex;
13981 VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13982 VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13983 VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13987 VectorCopy(decal->vertex3f[0], v3f);
13988 VectorCopy(decal->vertex3f[1], v3f + 3);
13989 VectorCopy(decal->vertex3f[2], v3f + 6);
13992 if (r_refdef.fogenabled)
13994 alpha = RSurf_FogVertex(v3f);
13995 VectorScale(c4f, alpha, c4f);
13996 alpha = RSurf_FogVertex(v3f + 3);
13997 VectorScale(c4f + 4, alpha, c4f + 4);
13998 alpha = RSurf_FogVertex(v3f + 6);
13999 VectorScale(c4f + 8, alpha, c4f + 8);
14010 r_refdef.stats.drawndecals += numtris;
14012 // now render the decals all at once
14013 // (this assumes they all use one particle font texture!)
14014 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);
14015 R_Mesh_ResetTextureState();
14016 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14017 GL_DepthMask(false);
14018 GL_DepthRange(0, 1);
14019 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14020 GL_DepthTest(true);
14021 GL_CullFace(GL_NONE);
14022 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14023 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14024 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14028 static void R_DrawModelDecals(void)
14032 // fade faster when there are too many decals
14033 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14034 for (i = 0;i < r_refdef.scene.numentities;i++)
14035 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14037 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14038 for (i = 0;i < r_refdef.scene.numentities;i++)
14039 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14040 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14042 R_DecalSystem_ApplySplatEntitiesQueue();
14044 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14045 for (i = 0;i < r_refdef.scene.numentities;i++)
14046 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14048 r_refdef.stats.totaldecals += numdecals;
14050 if (r_showsurfaces.integer)
14053 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14055 for (i = 0;i < r_refdef.scene.numentities;i++)
14057 if (!r_refdef.viewcache.entityvisible[i])
14059 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14060 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14064 extern cvar_t mod_collision_bih;
14065 void R_DrawDebugModel(void)
14067 entity_render_t *ent = rsurface.entity;
14068 int i, j, k, l, flagsmask;
14069 const msurface_t *surface;
14070 dp_model_t *model = ent->model;
14073 switch(vid.renderpath)
14075 case RENDERPATH_GL11:
14076 case RENDERPATH_GL13:
14077 case RENDERPATH_GL20:
14078 case RENDERPATH_CGGL:
14080 case RENDERPATH_D3D9:
14081 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14083 case RENDERPATH_D3D10:
14084 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14086 case RENDERPATH_D3D11:
14087 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14091 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14093 R_Mesh_ResetTextureState();
14094 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14095 GL_DepthRange(0, 1);
14096 GL_DepthTest(!r_showdisabledepthtest.integer);
14097 GL_DepthMask(false);
14098 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14100 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14104 qboolean cullbox = ent == r_refdef.scene.worldentity;
14105 const q3mbrush_t *brush;
14106 const bih_t *bih = &model->collision_bih;
14107 const bih_leaf_t *bihleaf;
14108 float vertex3f[3][3];
14109 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14111 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14113 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14115 switch (bihleaf->type)
14118 brush = model->brush.data_brushes + bihleaf->itemindex;
14119 if (brush->colbrushf && brush->colbrushf->numtriangles)
14121 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);
14122 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14123 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14126 case BIH_COLLISIONTRIANGLE:
14127 triangleindex = bihleaf->itemindex;
14128 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14129 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14130 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14131 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);
14132 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14133 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14135 case BIH_RENDERTRIANGLE:
14136 triangleindex = bihleaf->itemindex;
14137 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14138 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14139 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14140 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);
14141 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14142 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14148 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14150 if (r_showtris.integer || r_shownormals.integer)
14152 if (r_showdisabledepthtest.integer)
14154 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14155 GL_DepthMask(false);
14159 GL_BlendFunc(GL_ONE, GL_ZERO);
14160 GL_DepthMask(true);
14162 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14164 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14166 rsurface.texture = R_GetCurrentTexture(surface->texture);
14167 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14169 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14170 if (r_showtris.value > 0)
14172 if (!rsurface.texture->currentlayers->depthmask)
14173 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14174 else if (ent == r_refdef.scene.worldentity)
14175 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14177 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14178 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14179 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14181 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14184 if (r_shownormals.value < 0)
14186 qglBegin(GL_LINES);
14187 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14189 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14190 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14191 qglVertex3f(v[0], v[1], v[2]);
14192 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14193 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14194 qglVertex3f(v[0], v[1], v[2]);
14199 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
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]);
14213 qglBegin(GL_LINES);
14214 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14216 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14217 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14218 qglVertex3f(v[0], v[1], v[2]);
14219 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14220 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14221 qglVertex3f(v[0], v[1], v[2]);
14225 qglBegin(GL_LINES);
14226 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14228 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14229 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14230 qglVertex3f(v[0], v[1], v[2]);
14231 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14232 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14233 qglVertex3f(v[0], v[1], v[2]);
14240 rsurface.texture = NULL;
14244 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14245 int r_maxsurfacelist = 0;
14246 const msurface_t **r_surfacelist = NULL;
14247 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14249 int i, j, endj, flagsmask;
14250 dp_model_t *model = r_refdef.scene.worldmodel;
14251 msurface_t *surfaces;
14252 unsigned char *update;
14253 int numsurfacelist = 0;
14257 if (r_maxsurfacelist < model->num_surfaces)
14259 r_maxsurfacelist = model->num_surfaces;
14261 Mem_Free((msurface_t**)r_surfacelist);
14262 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14265 RSurf_ActiveWorldEntity();
14267 surfaces = model->data_surfaces;
14268 update = model->brushq1.lightmapupdateflags;
14270 // update light styles on this submodel
14271 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14273 model_brush_lightstyleinfo_t *style;
14274 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14276 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14278 int *list = style->surfacelist;
14279 style->value = r_refdef.scene.lightstylevalue[style->style];
14280 for (j = 0;j < style->numsurfaces;j++)
14281 update[list[j]] = true;
14286 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14290 R_DrawDebugModel();
14291 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14295 rsurface.lightmaptexture = NULL;
14296 rsurface.deluxemaptexture = NULL;
14297 rsurface.uselightmaptexture = false;
14298 rsurface.texture = NULL;
14299 rsurface.rtlight = NULL;
14300 numsurfacelist = 0;
14301 // add visible surfaces to draw list
14302 for (i = 0;i < model->nummodelsurfaces;i++)
14304 j = model->sortedmodelsurfaces[i];
14305 if (r_refdef.viewcache.world_surfacevisible[j])
14306 r_surfacelist[numsurfacelist++] = surfaces + j;
14308 // update lightmaps if needed
14309 if (model->brushq1.firstrender)
14311 model->brushq1.firstrender = false;
14312 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14314 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14318 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14319 if (r_refdef.viewcache.world_surfacevisible[j])
14321 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14323 // don't do anything if there were no surfaces
14324 if (!numsurfacelist)
14326 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14329 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14330 GL_AlphaTest(false);
14332 // add to stats if desired
14333 if (r_speeds.integer && !skysurfaces && !depthonly)
14335 r_refdef.stats.world_surfaces += numsurfacelist;
14336 for (j = 0;j < numsurfacelist;j++)
14337 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14340 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14343 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14345 int i, j, endj, flagsmask;
14346 dp_model_t *model = ent->model;
14347 msurface_t *surfaces;
14348 unsigned char *update;
14349 int numsurfacelist = 0;
14353 if (r_maxsurfacelist < model->num_surfaces)
14355 r_maxsurfacelist = model->num_surfaces;
14357 Mem_Free((msurface_t **)r_surfacelist);
14358 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14361 // if the model is static it doesn't matter what value we give for
14362 // wantnormals and wanttangents, so this logic uses only rules applicable
14363 // to a model, knowing that they are meaningless otherwise
14364 if (ent == r_refdef.scene.worldentity)
14365 RSurf_ActiveWorldEntity();
14366 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14367 RSurf_ActiveModelEntity(ent, false, false, false);
14369 RSurf_ActiveModelEntity(ent, true, true, true);
14370 else if (depthonly)
14372 switch (vid.renderpath)
14374 case RENDERPATH_GL20:
14375 case RENDERPATH_CGGL:
14376 case RENDERPATH_D3D9:
14377 case RENDERPATH_D3D10:
14378 case RENDERPATH_D3D11:
14379 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14381 case RENDERPATH_GL13:
14382 case RENDERPATH_GL11:
14383 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14389 switch (vid.renderpath)
14391 case RENDERPATH_GL20:
14392 case RENDERPATH_CGGL:
14393 case RENDERPATH_D3D9:
14394 case RENDERPATH_D3D10:
14395 case RENDERPATH_D3D11:
14396 RSurf_ActiveModelEntity(ent, true, true, false);
14398 case RENDERPATH_GL13:
14399 case RENDERPATH_GL11:
14400 RSurf_ActiveModelEntity(ent, true, false, false);
14405 surfaces = model->data_surfaces;
14406 update = model->brushq1.lightmapupdateflags;
14408 // update light styles
14409 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14411 model_brush_lightstyleinfo_t *style;
14412 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14414 if (style->value != r_refdef.scene.lightstylevalue[style->style])
14416 int *list = style->surfacelist;
14417 style->value = r_refdef.scene.lightstylevalue[style->style];
14418 for (j = 0;j < style->numsurfaces;j++)
14419 update[list[j]] = true;
14424 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14428 R_DrawDebugModel();
14429 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14433 rsurface.lightmaptexture = NULL;
14434 rsurface.deluxemaptexture = NULL;
14435 rsurface.uselightmaptexture = false;
14436 rsurface.texture = NULL;
14437 rsurface.rtlight = NULL;
14438 numsurfacelist = 0;
14439 // add visible surfaces to draw list
14440 for (i = 0;i < model->nummodelsurfaces;i++)
14441 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14442 // don't do anything if there were no surfaces
14443 if (!numsurfacelist)
14445 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14448 // update lightmaps if needed
14452 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14457 R_BuildLightMap(ent, surfaces + j);
14462 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14464 R_BuildLightMap(ent, surfaces + j);
14465 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14466 GL_AlphaTest(false);
14468 // add to stats if desired
14469 if (r_speeds.integer && !skysurfaces && !depthonly)
14471 r_refdef.stats.entities_surfaces += numsurfacelist;
14472 for (j = 0;j < numsurfacelist;j++)
14473 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14476 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14479 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14481 static texture_t texture;
14482 static msurface_t surface;
14483 const msurface_t *surfacelist = &surface;
14485 // fake enough texture and surface state to render this geometry
14487 texture.update_lastrenderframe = -1; // regenerate this texture
14488 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14489 texture.currentskinframe = skinframe;
14490 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14491 texture.offsetmapping = OFFSETMAPPING_OFF;
14492 texture.offsetscale = 1;
14493 texture.specularscalemod = 1;
14494 texture.specularpowermod = 1;
14496 surface.texture = &texture;
14497 surface.num_triangles = numtriangles;
14498 surface.num_firsttriangle = firsttriangle;
14499 surface.num_vertices = numvertices;
14500 surface.num_firstvertex = firstvertex;
14503 rsurface.texture = R_GetCurrentTexture(surface.texture);
14504 rsurface.lightmaptexture = NULL;
14505 rsurface.deluxemaptexture = NULL;
14506 rsurface.uselightmaptexture = false;
14507 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14510 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)
14512 static msurface_t surface;
14513 const msurface_t *surfacelist = &surface;
14515 // fake enough texture and surface state to render this geometry
14516 surface.texture = texture;
14517 surface.num_triangles = numtriangles;
14518 surface.num_firsttriangle = firsttriangle;
14519 surface.num_vertices = numvertices;
14520 surface.num_firstvertex = firstvertex;
14523 rsurface.texture = R_GetCurrentTexture(surface.texture);
14524 rsurface.lightmaptexture = NULL;
14525 rsurface.deluxemaptexture = NULL;
14526 rsurface.uselightmaptexture = false;
14527 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);