]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix fog for GL_SRC_ALPHA GL_ONE
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 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)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 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)"};
131 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
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 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)"};
149 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)"};
150 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)"};
151 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_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 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)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 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"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 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"};
189
190 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"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 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"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 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"};
206
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 #include "shader_glsl.h"
597 ;
598
599 const char *builtinhlslshaderstring =
600 #include "shader_hlsl.h"
601 ;
602
603 char *glslshaderstring = NULL;
604 char *hlslshaderstring = NULL;
605
606 //=======================================================================================================================================================
607
608 typedef struct shaderpermutationinfo_s
609 {
610         const char *pretext;
611         const char *name;
612 }
613 shaderpermutationinfo_t;
614
615 typedef struct shadermodeinfo_s
616 {
617         const char *vertexfilename;
618         const char *geometryfilename;
619         const char *fragmentfilename;
620         const char *pretext;
621         const char *name;
622 }
623 shadermodeinfo_t;
624
625 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
626 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
627 {
628         {"#define USEDIFFUSE\n", " diffuse"},
629         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
630         {"#define USEVIEWTINT\n", " viewtint"},
631         {"#define USECOLORMAPPING\n", " colormapping"},
632         {"#define USESATURATION\n", " saturation"},
633         {"#define USEFOGINSIDE\n", " foginside"},
634         {"#define USEFOGOUTSIDE\n", " fogoutside"},
635         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
636         {"#define USEGAMMARAMPS\n", " gammaramps"},
637         {"#define USECUBEFILTER\n", " cubefilter"},
638         {"#define USEGLOW\n", " glow"},
639         {"#define USEBLOOM\n", " bloom"},
640         {"#define USESPECULAR\n", " specular"},
641         {"#define USEPOSTPROCESSING\n", " postprocessing"},
642         {"#define USEREFLECTION\n", " reflection"},
643         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
644         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
645         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
646         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
647         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
648         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
649         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
650         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
651         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
652         {"#define USEALPHAKILL\n", " alphakill"},
653         {"#define USEREFLECTCUBE\n", " reflectcube"},
654         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
655         {"#define USEBOUNCEGRID\n", " bouncegrid"},
656 };
657
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
660 {
661         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
677 };
678
679 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
680 {
681         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
697 };
698
699 struct r_glsl_permutation_s;
700 typedef struct r_glsl_permutation_s
701 {
702         /// hash lookup data
703         struct r_glsl_permutation_s *hashnext;
704         unsigned int mode;
705         unsigned int permutation;
706
707         /// indicates if we have tried compiling this permutation already
708         qboolean compiled;
709         /// 0 if compilation failed
710         int program;
711         // texture units assigned to each detected uniform
712         int tex_Texture_First;
713         int tex_Texture_Second;
714         int tex_Texture_GammaRamps;
715         int tex_Texture_Normal;
716         int tex_Texture_Color;
717         int tex_Texture_Gloss;
718         int tex_Texture_Glow;
719         int tex_Texture_SecondaryNormal;
720         int tex_Texture_SecondaryColor;
721         int tex_Texture_SecondaryGloss;
722         int tex_Texture_SecondaryGlow;
723         int tex_Texture_Pants;
724         int tex_Texture_Shirt;
725         int tex_Texture_FogHeightTexture;
726         int tex_Texture_FogMask;
727         int tex_Texture_Lightmap;
728         int tex_Texture_Deluxemap;
729         int tex_Texture_Attenuation;
730         int tex_Texture_Cube;
731         int tex_Texture_Refraction;
732         int tex_Texture_Reflection;
733         int tex_Texture_ShadowMap2D;
734         int tex_Texture_CubeProjection;
735         int tex_Texture_ScreenDepth;
736         int tex_Texture_ScreenNormalMap;
737         int tex_Texture_ScreenDiffuse;
738         int tex_Texture_ScreenSpecular;
739         int tex_Texture_ReflectMask;
740         int tex_Texture_ReflectCube;
741         int tex_Texture_BounceGrid;
742         /// locations of detected uniforms in program object, or -1 if not found
743         int loc_Texture_First;
744         int loc_Texture_Second;
745         int loc_Texture_GammaRamps;
746         int loc_Texture_Normal;
747         int loc_Texture_Color;
748         int loc_Texture_Gloss;
749         int loc_Texture_Glow;
750         int loc_Texture_SecondaryNormal;
751         int loc_Texture_SecondaryColor;
752         int loc_Texture_SecondaryGloss;
753         int loc_Texture_SecondaryGlow;
754         int loc_Texture_Pants;
755         int loc_Texture_Shirt;
756         int loc_Texture_FogHeightTexture;
757         int loc_Texture_FogMask;
758         int loc_Texture_Lightmap;
759         int loc_Texture_Deluxemap;
760         int loc_Texture_Attenuation;
761         int loc_Texture_Cube;
762         int loc_Texture_Refraction;
763         int loc_Texture_Reflection;
764         int loc_Texture_ShadowMap2D;
765         int loc_Texture_CubeProjection;
766         int loc_Texture_ScreenDepth;
767         int loc_Texture_ScreenNormalMap;
768         int loc_Texture_ScreenDiffuse;
769         int loc_Texture_ScreenSpecular;
770         int loc_Texture_ReflectMask;
771         int loc_Texture_ReflectCube;
772         int loc_Texture_BounceGrid;
773         int loc_Alpha;
774         int loc_BloomBlur_Parameters;
775         int loc_ClientTime;
776         int loc_Color_Ambient;
777         int loc_Color_Diffuse;
778         int loc_Color_Specular;
779         int loc_Color_Glow;
780         int loc_Color_Pants;
781         int loc_Color_Shirt;
782         int loc_DeferredColor_Ambient;
783         int loc_DeferredColor_Diffuse;
784         int loc_DeferredColor_Specular;
785         int loc_DeferredMod_Diffuse;
786         int loc_DeferredMod_Specular;
787         int loc_DistortScaleRefractReflect;
788         int loc_EyePosition;
789         int loc_FogColor;
790         int loc_FogHeightFade;
791         int loc_FogPlane;
792         int loc_FogPlaneViewDist;
793         int loc_FogRangeRecip;
794         int loc_LightColor;
795         int loc_LightDir;
796         int loc_LightPosition;
797         int loc_OffsetMapping_Scale;
798         int loc_PixelSize;
799         int loc_ReflectColor;
800         int loc_ReflectFactor;
801         int loc_ReflectOffset;
802         int loc_RefractColor;
803         int loc_Saturation;
804         int loc_ScreenCenterRefractReflect;
805         int loc_ScreenScaleRefractReflect;
806         int loc_ScreenToDepth;
807         int loc_ShadowMap_Parameters;
808         int loc_ShadowMap_TextureScale;
809         int loc_SpecularPower;
810         int loc_UserVec1;
811         int loc_UserVec2;
812         int loc_UserVec3;
813         int loc_UserVec4;
814         int loc_ViewTintColor;
815         int loc_ViewToLight;
816         int loc_ModelToLight;
817         int loc_TexMatrix;
818         int loc_BackgroundTexMatrix;
819         int loc_ModelViewProjectionMatrix;
820         int loc_ModelViewMatrix;
821         int loc_PixelToScreenTexCoord;
822         int loc_ModelToReflectCube;
823         int loc_ShadowMapMatrix;
824         int loc_BloomColorSubtract;
825         int loc_NormalmapScrollBlend;
826         int loc_BounceGridMatrix;
827         int loc_BounceGridIntensity;
828 }
829 r_glsl_permutation_t;
830
831 #define SHADERPERMUTATION_HASHSIZE 256
832
833
834 // non-degradable "lightweight" shader parameters to keep the permutations simpler
835 // these can NOT degrade! only use for simple stuff
836 enum
837 {
838         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
839         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
840         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
841         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
842         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
843         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
844 };
845 #define SHADERSTATICPARMS_COUNT 6
846
847 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
848 static int shaderstaticparms_count = 0;
849
850 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
851 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
852 qboolean R_CompileShader_CheckStaticParms(void)
853 {
854         static int r_compileshader_staticparms_save[1];
855         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
856         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
857
858         // detect all
859         if (r_glsl_saturation_redcompensate.integer)
860                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
861         if (r_shadow_glossexact.integer)
862                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
863         if (r_glsl_postprocess.integer)
864         {
865                 if (r_glsl_postprocess_uservec1_enable.integer)
866                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
867                 if (r_glsl_postprocess_uservec2_enable.integer)
868                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
869                 if (r_glsl_postprocess_uservec3_enable.integer)
870                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
871                 if (r_glsl_postprocess_uservec4_enable.integer)
872                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
873         }
874         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
875 }
876
877 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
878         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
879                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
880         else \
881                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
882 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
883 {
884         shaderstaticparms_count = 0;
885
886         // emit all
887         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
888         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
889         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
893 }
894
895 /// information about each possible shader permutation
896 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
897 /// currently selected permutation
898 r_glsl_permutation_t *r_glsl_permutation;
899 /// storage for permutations linked in the hash table
900 memexpandablearray_t r_glsl_permutationarray;
901
902 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
903 {
904         //unsigned int hashdepth = 0;
905         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
906         r_glsl_permutation_t *p;
907         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
908         {
909                 if (p->mode == mode && p->permutation == permutation)
910                 {
911                         //if (hashdepth > 10)
912                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
913                         return p;
914                 }
915                 //hashdepth++;
916         }
917         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
918         p->mode = mode;
919         p->permutation = permutation;
920         p->hashnext = r_glsl_permutationhash[mode][hashindex];
921         r_glsl_permutationhash[mode][hashindex] = p;
922         //if (hashdepth > 10)
923         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
924         return p;
925 }
926
927 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
928 {
929         char *shaderstring;
930         if (!filename || !filename[0])
931                 return NULL;
932         if (!strcmp(filename, "glsl/default.glsl"))
933         {
934                 if (!glslshaderstring)
935                 {
936                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
937                         if (glslshaderstring)
938                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
939                         else
940                                 glslshaderstring = (char *)builtinshaderstring;
941                 }
942                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
943                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
944                 return shaderstring;
945         }
946         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
947         if (shaderstring)
948         {
949                 if (printfromdisknotice)
950                         Con_DPrintf("from disk %s... ", filename);
951                 return shaderstring;
952         }
953         return shaderstring;
954 }
955
956 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
957 {
958         int i;
959         int sampler;
960         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
961         char *vertexstring, *geometrystring, *fragmentstring;
962         char permutationname[256];
963         int vertstrings_count = 0;
964         int geomstrings_count = 0;
965         int fragstrings_count = 0;
966         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
967         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969
970         if (p->compiled)
971                 return;
972         p->compiled = true;
973         p->program = 0;
974
975         permutationname[0] = 0;
976         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
977         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
978         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
979
980         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
981
982         // the first pretext is which type of shader to compile as
983         // (later these will all be bound together as a program object)
984         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
985         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
986         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
987
988         // the second pretext is the mode (for example a light source)
989         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
990         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
991         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
992         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
993
994         // now add all the permutation pretexts
995         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
996         {
997                 if (permutation & (1<<i))
998                 {
999                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1000                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1001                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1002                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1003                 }
1004                 else
1005                 {
1006                         // keep line numbers correct
1007                         vertstrings_list[vertstrings_count++] = "\n";
1008                         geomstrings_list[geomstrings_count++] = "\n";
1009                         fragstrings_list[fragstrings_count++] = "\n";
1010                 }
1011         }
1012
1013         // add static parms
1014         R_CompileShader_AddStaticParms(mode, permutation);
1015         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1016         vertstrings_count += shaderstaticparms_count;
1017         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1018         geomstrings_count += shaderstaticparms_count;
1019         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1020         fragstrings_count += shaderstaticparms_count;
1021
1022         // now append the shader text itself
1023         vertstrings_list[vertstrings_count++] = vertexstring;
1024         geomstrings_list[geomstrings_count++] = geometrystring;
1025         fragstrings_list[fragstrings_count++] = fragmentstring;
1026
1027         // if any sources were NULL, clear the respective list
1028         if (!vertexstring)
1029                 vertstrings_count = 0;
1030         if (!geometrystring)
1031                 geomstrings_count = 0;
1032         if (!fragmentstring)
1033                 fragstrings_count = 0;
1034
1035         // compile the shader program
1036         if (vertstrings_count + geomstrings_count + fragstrings_count)
1037                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1038         if (p->program)
1039         {
1040                 CHECKGLERROR
1041                 qglUseProgram(p->program);CHECKGLERROR
1042                 // look up all the uniform variable names we care about, so we don't
1043                 // have to look them up every time we set them
1044
1045                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1046                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1047                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1048                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1049                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1050                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1051                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1052                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1053                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1054                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1055                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1056                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1057                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1058                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1059                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1060                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1061                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1062                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1063                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1064                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1065                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1066                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1067                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1068                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1069                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1070                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1071                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1072                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1073                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1074                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1075                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1076                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1077                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1078                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1079                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1080                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1081                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1082                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1083                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1084                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1085                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1086                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1087                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1088                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1089                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1090                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1091                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1092                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1093                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1094                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1095                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1096                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1097                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1098                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1099                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1100                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1101                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1102                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1103                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1104                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1105                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1106                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1107                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1108                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1109                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1110                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1111                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1112                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1113                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1114                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1115                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1116                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1117                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1118                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1119                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1120                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1121                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1122                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1123                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1124                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1125                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1126                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1127                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1128                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1129                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1130                 // initialize the samplers to refer to the texture units we use
1131                 p->tex_Texture_First = -1;
1132                 p->tex_Texture_Second = -1;
1133                 p->tex_Texture_GammaRamps = -1;
1134                 p->tex_Texture_Normal = -1;
1135                 p->tex_Texture_Color = -1;
1136                 p->tex_Texture_Gloss = -1;
1137                 p->tex_Texture_Glow = -1;
1138                 p->tex_Texture_SecondaryNormal = -1;
1139                 p->tex_Texture_SecondaryColor = -1;
1140                 p->tex_Texture_SecondaryGloss = -1;
1141                 p->tex_Texture_SecondaryGlow = -1;
1142                 p->tex_Texture_Pants = -1;
1143                 p->tex_Texture_Shirt = -1;
1144                 p->tex_Texture_FogHeightTexture = -1;
1145                 p->tex_Texture_FogMask = -1;
1146                 p->tex_Texture_Lightmap = -1;
1147                 p->tex_Texture_Deluxemap = -1;
1148                 p->tex_Texture_Attenuation = -1;
1149                 p->tex_Texture_Cube = -1;
1150                 p->tex_Texture_Refraction = -1;
1151                 p->tex_Texture_Reflection = -1;
1152                 p->tex_Texture_ShadowMap2D = -1;
1153                 p->tex_Texture_CubeProjection = -1;
1154                 p->tex_Texture_ScreenDepth = -1;
1155                 p->tex_Texture_ScreenNormalMap = -1;
1156                 p->tex_Texture_ScreenDiffuse = -1;
1157                 p->tex_Texture_ScreenSpecular = -1;
1158                 p->tex_Texture_ReflectMask = -1;
1159                 p->tex_Texture_ReflectCube = -1;
1160                 p->tex_Texture_BounceGrid = -1;
1161                 sampler = 0;
1162                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1163                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1164                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1165                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1166                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1167                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1168                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1169                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1170                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1171                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1172                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1173                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1174                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1175                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1176                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1177                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1178                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1179                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1180                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1181                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1182                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1183                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1184                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1185                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1186                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1187                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1188                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1189                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1190                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1191                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1192                 CHECKGLERROR
1193                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1194         }
1195         else
1196                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1197
1198         // free the strings
1199         if (vertexstring)
1200                 Mem_Free(vertexstring);
1201         if (geometrystring)
1202                 Mem_Free(geometrystring);
1203         if (fragmentstring)
1204                 Mem_Free(fragmentstring);
1205 }
1206
1207 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1208 {
1209         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1210         if (r_glsl_permutation != perm)
1211         {
1212                 r_glsl_permutation = perm;
1213                 if (!r_glsl_permutation->program)
1214                 {
1215                         if (!r_glsl_permutation->compiled)
1216                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1217                         if (!r_glsl_permutation->program)
1218                         {
1219                                 // remove features until we find a valid permutation
1220                                 int i;
1221                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1222                                 {
1223                                         // reduce i more quickly whenever it would not remove any bits
1224                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1225                                         if (!(permutation & j))
1226                                                 continue;
1227                                         permutation -= j;
1228                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1229                                         if (!r_glsl_permutation->compiled)
1230                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1231                                         if (r_glsl_permutation->program)
1232                                                 break;
1233                                 }
1234                                 if (i >= SHADERPERMUTATION_COUNT)
1235                                 {
1236                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1237                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238                                         qglUseProgram(0);CHECKGLERROR
1239                                         return; // no bit left to clear, entire mode is broken
1240                                 }
1241                         }
1242                 }
1243                 CHECKGLERROR
1244                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1245         }
1246         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1247         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1248         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1249 }
1250
1251 #ifdef SUPPORTD3D
1252
1253 #ifdef SUPPORTD3D
1254 #include <d3d9.h>
1255 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1256 extern D3DCAPS9 vid_d3d9caps;
1257 #endif
1258
1259 struct r_hlsl_permutation_s;
1260 typedef struct r_hlsl_permutation_s
1261 {
1262         /// hash lookup data
1263         struct r_hlsl_permutation_s *hashnext;
1264         unsigned int mode;
1265         unsigned int permutation;
1266
1267         /// indicates if we have tried compiling this permutation already
1268         qboolean compiled;
1269         /// NULL if compilation failed
1270         IDirect3DVertexShader9 *vertexshader;
1271         IDirect3DPixelShader9 *pixelshader;
1272 }
1273 r_hlsl_permutation_t;
1274
1275 typedef enum D3DVSREGISTER_e
1276 {
1277         D3DVSREGISTER_TexMatrix = 0, // float4x4
1278         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1279         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1280         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1281         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1282         D3DVSREGISTER_ModelToLight = 20, // float4x4
1283         D3DVSREGISTER_EyePosition = 24,
1284         D3DVSREGISTER_FogPlane = 25,
1285         D3DVSREGISTER_LightDir = 26,
1286         D3DVSREGISTER_LightPosition = 27,
1287 }
1288 D3DVSREGISTER_t;
1289
1290 typedef enum D3DPSREGISTER_e
1291 {
1292         D3DPSREGISTER_Alpha = 0,
1293         D3DPSREGISTER_BloomBlur_Parameters = 1,
1294         D3DPSREGISTER_ClientTime = 2,
1295         D3DPSREGISTER_Color_Ambient = 3,
1296         D3DPSREGISTER_Color_Diffuse = 4,
1297         D3DPSREGISTER_Color_Specular = 5,
1298         D3DPSREGISTER_Color_Glow = 6,
1299         D3DPSREGISTER_Color_Pants = 7,
1300         D3DPSREGISTER_Color_Shirt = 8,
1301         D3DPSREGISTER_DeferredColor_Ambient = 9,
1302         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1303         D3DPSREGISTER_DeferredColor_Specular = 11,
1304         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1305         D3DPSREGISTER_DeferredMod_Specular = 13,
1306         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1307         D3DPSREGISTER_EyePosition = 15, // unused
1308         D3DPSREGISTER_FogColor = 16,
1309         D3DPSREGISTER_FogHeightFade = 17,
1310         D3DPSREGISTER_FogPlane = 18,
1311         D3DPSREGISTER_FogPlaneViewDist = 19,
1312         D3DPSREGISTER_FogRangeRecip = 20,
1313         D3DPSREGISTER_LightColor = 21,
1314         D3DPSREGISTER_LightDir = 22, // unused
1315         D3DPSREGISTER_LightPosition = 23,
1316         D3DPSREGISTER_OffsetMapping_Scale = 24,
1317         D3DPSREGISTER_PixelSize = 25,
1318         D3DPSREGISTER_ReflectColor = 26,
1319         D3DPSREGISTER_ReflectFactor = 27,
1320         D3DPSREGISTER_ReflectOffset = 28,
1321         D3DPSREGISTER_RefractColor = 29,
1322         D3DPSREGISTER_Saturation = 30,
1323         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1324         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1325         D3DPSREGISTER_ScreenToDepth = 33,
1326         D3DPSREGISTER_ShadowMap_Parameters = 34,
1327         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1328         D3DPSREGISTER_SpecularPower = 36,
1329         D3DPSREGISTER_UserVec1 = 37,
1330         D3DPSREGISTER_UserVec2 = 38,
1331         D3DPSREGISTER_UserVec3 = 39,
1332         D3DPSREGISTER_UserVec4 = 40,
1333         D3DPSREGISTER_ViewTintColor = 41,
1334         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1335         D3DPSREGISTER_BloomColorSubtract = 43,
1336         D3DPSREGISTER_ViewToLight = 44, // float4x4
1337         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1338         D3DPSREGISTER_NormalmapScrollBlend = 52,
1339         // next at 53
1340 }
1341 D3DPSREGISTER_t;
1342
1343 /// information about each possible shader permutation
1344 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1345 /// currently selected permutation
1346 r_hlsl_permutation_t *r_hlsl_permutation;
1347 /// storage for permutations linked in the hash table
1348 memexpandablearray_t r_hlsl_permutationarray;
1349
1350 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1351 {
1352         //unsigned int hashdepth = 0;
1353         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1354         r_hlsl_permutation_t *p;
1355         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1356         {
1357                 if (p->mode == mode && p->permutation == permutation)
1358                 {
1359                         //if (hashdepth > 10)
1360                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1361                         return p;
1362                 }
1363                 //hashdepth++;
1364         }
1365         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1366         p->mode = mode;
1367         p->permutation = permutation;
1368         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1369         r_hlsl_permutationhash[mode][hashindex] = p;
1370         //if (hashdepth > 10)
1371         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1372         return p;
1373 }
1374
1375 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1376 {
1377         char *shaderstring;
1378         if (!filename || !filename[0])
1379                 return NULL;
1380         if (!strcmp(filename, "hlsl/default.hlsl"))
1381         {
1382                 if (!hlslshaderstring)
1383                 {
1384                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1385                         if (hlslshaderstring)
1386                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1387                         else
1388                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1389                 }
1390                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1391                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1392                 return shaderstring;
1393         }
1394         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1395         if (shaderstring)
1396         {
1397                 if (printfromdisknotice)
1398                         Con_DPrintf("from disk %s... ", filename);
1399                 return shaderstring;
1400         }
1401         return shaderstring;
1402 }
1403
1404 #include <d3dx9.h>
1405 //#include <d3dx9shader.h>
1406 //#include <d3dx9mesh.h>
1407
1408 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1409 {
1410         DWORD *vsbin = NULL;
1411         DWORD *psbin = NULL;
1412         fs_offset_t vsbinsize;
1413         fs_offset_t psbinsize;
1414 //      IDirect3DVertexShader9 *vs = NULL;
1415 //      IDirect3DPixelShader9 *ps = NULL;
1416         ID3DXBuffer *vslog = NULL;
1417         ID3DXBuffer *vsbuffer = NULL;
1418         ID3DXConstantTable *vsconstanttable = NULL;
1419         ID3DXBuffer *pslog = NULL;
1420         ID3DXBuffer *psbuffer = NULL;
1421         ID3DXConstantTable *psconstanttable = NULL;
1422         int vsresult = 0;
1423         int psresult = 0;
1424         char temp[MAX_INPUTLINE];
1425         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1426         qboolean debugshader = gl_paranoid.integer != 0;
1427         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1428         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1429         if (!debugshader)
1430         {
1431                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1432                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1433         }
1434         if ((!vsbin && vertstring) || (!psbin && fragstring))
1435         {
1436                 const char* dllnames_d3dx9 [] =
1437                 {
1438                         "d3dx9_43.dll",
1439                         "d3dx9_42.dll",
1440                         "d3dx9_41.dll",
1441                         "d3dx9_40.dll",
1442                         "d3dx9_39.dll",
1443                         "d3dx9_38.dll",
1444                         "d3dx9_37.dll",
1445                         "d3dx9_36.dll",
1446                         "d3dx9_35.dll",
1447                         "d3dx9_34.dll",
1448                         "d3dx9_33.dll",
1449                         "d3dx9_32.dll",
1450                         "d3dx9_31.dll",
1451                         "d3dx9_30.dll",
1452                         "d3dx9_29.dll",
1453                         "d3dx9_28.dll",
1454                         "d3dx9_27.dll",
1455                         "d3dx9_26.dll",
1456                         "d3dx9_25.dll",
1457                         "d3dx9_24.dll",
1458                         NULL
1459                 };
1460                 dllhandle_t d3dx9_dll = NULL;
1461                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1462                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1463                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1464                 dllfunction_t d3dx9_dllfuncs[] =
1465                 {
1466                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1467                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1468                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1469                         {NULL, NULL}
1470                 };
1471                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1472                 {
1473                         DWORD shaderflags = 0;
1474                         if (debugshader)
1475                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1476                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1477                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1478                         if (vertstring && vertstring[0])
1479                         {
1480                                 if (debugshader)
1481                                 {
1482 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1483 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1484                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1485                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1486                                 }
1487                                 else
1488                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1489                                 if (vsbuffer)
1490                                 {
1491                                         vsbinsize = vsbuffer->GetBufferSize();
1492                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1493                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1494                                         vsbuffer->Release();
1495                                 }
1496                                 if (vslog)
1497                                 {
1498                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1499                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1500                                         vslog->Release();
1501                                 }
1502                         }
1503                         if (fragstring && fragstring[0])
1504                         {
1505                                 if (debugshader)
1506                                 {
1507 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1508 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1509                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1510                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1511                                 }
1512                                 else
1513                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1514                                 if (psbuffer)
1515                                 {
1516                                         psbinsize = psbuffer->GetBufferSize();
1517                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1518                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1519                                         psbuffer->Release();
1520                                 }
1521                                 if (pslog)
1522                                 {
1523                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1524                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1525                                         pslog->Release();
1526                                 }
1527                         }
1528                         Sys_UnloadLibrary(&d3dx9_dll);
1529                 }
1530                 else
1531                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1532         }
1533         if (vsbin && psbin)
1534         {
1535                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1536                 if (FAILED(vsresult))
1537                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1538                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1539                 if (FAILED(psresult))
1540                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1541         }
1542         // free the shader data
1543         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1544         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1545 }
1546
1547 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1548 {
1549         int i;
1550         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1551         int vertstring_length = 0;
1552         int geomstring_length = 0;
1553         int fragstring_length = 0;
1554         char *t;
1555         char *vertexstring, *geometrystring, *fragmentstring;
1556         char *vertstring, *geomstring, *fragstring;
1557         char permutationname[256];
1558         char cachename[256];
1559         int vertstrings_count = 0;
1560         int geomstrings_count = 0;
1561         int fragstrings_count = 0;
1562         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1563         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1565
1566         if (p->compiled)
1567                 return;
1568         p->compiled = true;
1569         p->vertexshader = NULL;
1570         p->pixelshader = NULL;
1571
1572         permutationname[0] = 0;
1573         cachename[0] = 0;
1574         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1575         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1576         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1577
1578         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1579         strlcat(cachename, "hlsl/", sizeof(cachename));
1580
1581         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1582         vertstrings_count = 0;
1583         geomstrings_count = 0;
1584         fragstrings_count = 0;
1585         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1586         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1587         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1588
1589         // the first pretext is which type of shader to compile as
1590         // (later these will all be bound together as a program object)
1591         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1592         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1593         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1594
1595         // the second pretext is the mode (for example a light source)
1596         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1597         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1598         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1599         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1600         strlcat(cachename, modeinfo->name, sizeof(cachename));
1601
1602         // now add all the permutation pretexts
1603         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1604         {
1605                 if (permutation & (1<<i))
1606                 {
1607                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1608                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1609                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1610                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1611                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1612                 }
1613                 else
1614                 {
1615                         // keep line numbers correct
1616                         vertstrings_list[vertstrings_count++] = "\n";
1617                         geomstrings_list[geomstrings_count++] = "\n";
1618                         fragstrings_list[fragstrings_count++] = "\n";
1619                 }
1620         }
1621
1622         // add static parms
1623         R_CompileShader_AddStaticParms(mode, permutation);
1624         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1625         vertstrings_count += shaderstaticparms_count;
1626         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1627         geomstrings_count += shaderstaticparms_count;
1628         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1629         fragstrings_count += shaderstaticparms_count;
1630
1631         // replace spaces in the cachename with _ characters
1632         for (i = 0;cachename[i];i++)
1633                 if (cachename[i] == ' ')
1634                         cachename[i] = '_';
1635
1636         // now append the shader text itself
1637         vertstrings_list[vertstrings_count++] = vertexstring;
1638         geomstrings_list[geomstrings_count++] = geometrystring;
1639         fragstrings_list[fragstrings_count++] = fragmentstring;
1640
1641         // if any sources were NULL, clear the respective list
1642         if (!vertexstring)
1643                 vertstrings_count = 0;
1644         if (!geometrystring)
1645                 geomstrings_count = 0;
1646         if (!fragmentstring)
1647                 fragstrings_count = 0;
1648
1649         vertstring_length = 0;
1650         for (i = 0;i < vertstrings_count;i++)
1651                 vertstring_length += strlen(vertstrings_list[i]);
1652         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1653         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1654                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1655
1656         geomstring_length = 0;
1657         for (i = 0;i < geomstrings_count;i++)
1658                 geomstring_length += strlen(geomstrings_list[i]);
1659         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1660         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1661                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1662
1663         fragstring_length = 0;
1664         for (i = 0;i < fragstrings_count;i++)
1665                 fragstring_length += strlen(fragstrings_list[i]);
1666         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1667         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1668                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1669
1670         // try to load the cached shader, or generate one
1671         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1672
1673         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1674                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1675         else
1676                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1677
1678         // free the strings
1679         if (vertstring)
1680                 Mem_Free(vertstring);
1681         if (geomstring)
1682                 Mem_Free(geomstring);
1683         if (fragstring)
1684                 Mem_Free(fragstring);
1685         if (vertexstring)
1686                 Mem_Free(vertexstring);
1687         if (geometrystring)
1688                 Mem_Free(geometrystring);
1689         if (fragmentstring)
1690                 Mem_Free(fragmentstring);
1691 }
1692
1693 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1694 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1695 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);}
1696 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);}
1697 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);}
1698 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);}
1699
1700 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1701 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1702 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);}
1703 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);}
1704 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);}
1705 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);}
1706
1707 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1708 {
1709         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1710         if (r_hlsl_permutation != perm)
1711         {
1712                 r_hlsl_permutation = perm;
1713                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1714                 {
1715                         if (!r_hlsl_permutation->compiled)
1716                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1717                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1718                         {
1719                                 // remove features until we find a valid permutation
1720                                 int i;
1721                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1722                                 {
1723                                         // reduce i more quickly whenever it would not remove any bits
1724                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1725                                         if (!(permutation & j))
1726                                                 continue;
1727                                         permutation -= j;
1728                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1729                                         if (!r_hlsl_permutation->compiled)
1730                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1731                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1732                                                 break;
1733                                 }
1734                                 if (i >= SHADERPERMUTATION_COUNT)
1735                                 {
1736                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1737                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738                                         return; // no bit left to clear, entire mode is broken
1739                                 }
1740                         }
1741                 }
1742                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1743                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1744         }
1745         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1746         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1747         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1748 }
1749 #endif
1750
1751 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1752 {
1753         DPSOFTRAST_SetShader(mode, permutation);
1754         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1755         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1756         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1757 }
1758
1759 void R_GLSL_Restart_f(void)
1760 {
1761         unsigned int i, limit;
1762         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1763                 Mem_Free(glslshaderstring);
1764         glslshaderstring = NULL;
1765         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1766                 Mem_Free(hlslshaderstring);
1767         hlslshaderstring = NULL;
1768         switch(vid.renderpath)
1769         {
1770         case RENDERPATH_D3D9:
1771 #ifdef SUPPORTD3D
1772                 {
1773                         r_hlsl_permutation_t *p;
1774                         r_hlsl_permutation = NULL;
1775                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1776                         for (i = 0;i < limit;i++)
1777                         {
1778                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1779                                 {
1780                                         if (p->vertexshader)
1781                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1782                                         if (p->pixelshader)
1783                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1784                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1785                                 }
1786                         }
1787                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1788                 }
1789 #endif
1790                 break;
1791         case RENDERPATH_D3D10:
1792                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1793                 break;
1794         case RENDERPATH_D3D11:
1795                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1796                 break;
1797         case RENDERPATH_GL20:
1798         case RENDERPATH_GLES2:
1799                 {
1800                         r_glsl_permutation_t *p;
1801                         r_glsl_permutation = NULL;
1802                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1803                         for (i = 0;i < limit;i++)
1804                         {
1805                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1806                                 {
1807                                         GL_Backend_FreeProgram(p->program);
1808                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1809                                 }
1810                         }
1811                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1812                 }
1813                 break;
1814         case RENDERPATH_GL13:
1815         case RENDERPATH_GL11:
1816                 break;
1817         case RENDERPATH_SOFT:
1818                 break;
1819         }
1820 }
1821
1822 void R_GLSL_DumpShader_f(void)
1823 {
1824         int i;
1825         qfile_t *file;
1826
1827         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1828         if (file)
1829         {
1830                 FS_Print(file, "/* The engine may define the following macros:\n");
1831                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1832                 for (i = 0;i < SHADERMODE_COUNT;i++)
1833                         FS_Print(file, glslshadermodeinfo[i].pretext);
1834                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1835                         FS_Print(file, shaderpermutationinfo[i].pretext);
1836                 FS_Print(file, "*/\n");
1837                 FS_Print(file, builtinshaderstring);
1838                 FS_Close(file);
1839                 Con_Printf("glsl/default.glsl written\n");
1840         }
1841         else
1842                 Con_Printf("failed to write to glsl/default.glsl\n");
1843
1844         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1845         if (file)
1846         {
1847                 FS_Print(file, "/* The engine may define the following macros:\n");
1848                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1849                 for (i = 0;i < SHADERMODE_COUNT;i++)
1850                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1851                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852                         FS_Print(file, shaderpermutationinfo[i].pretext);
1853                 FS_Print(file, "*/\n");
1854                 FS_Print(file, builtinhlslshaderstring);
1855                 FS_Close(file);
1856                 Con_Printf("hlsl/default.hlsl written\n");
1857         }
1858         else
1859                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1860 }
1861
1862 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1863 {
1864         if (!second)
1865                 texturemode = GL_MODULATE;
1866         switch (vid.renderpath)
1867         {
1868         case RENDERPATH_D3D9:
1869 #ifdef SUPPORTD3D
1870                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1871                 R_Mesh_TexBind(GL20TU_FIRST , first );
1872                 R_Mesh_TexBind(GL20TU_SECOND, second);
1873 #endif
1874                 break;
1875         case RENDERPATH_D3D10:
1876                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1877                 break;
1878         case RENDERPATH_D3D11:
1879                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1880                 break;
1881         case RENDERPATH_GL20:
1882         case RENDERPATH_GLES2:
1883                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1884                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1885                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1886                 break;
1887         case RENDERPATH_GL13:
1888                 R_Mesh_TexBind(0, first );
1889                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1890                 R_Mesh_TexBind(1, second);
1891                 if (second)
1892                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1893                 break;
1894         case RENDERPATH_GL11:
1895                 R_Mesh_TexBind(0, first );
1896                 break;
1897         case RENDERPATH_SOFT:
1898                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1899                 R_Mesh_TexBind(GL20TU_FIRST , first );
1900                 R_Mesh_TexBind(GL20TU_SECOND, second);
1901                 break;
1902         }
1903 }
1904
1905 void R_SetupShader_DepthOrShadow(void)
1906 {
1907         switch (vid.renderpath)
1908         {
1909         case RENDERPATH_D3D9:
1910 #ifdef SUPPORTD3D
1911                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1912 #endif
1913                 break;
1914         case RENDERPATH_D3D10:
1915                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916                 break;
1917         case RENDERPATH_D3D11:
1918                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919                 break;
1920         case RENDERPATH_GL20:
1921         case RENDERPATH_GLES2:
1922                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1923                 break;
1924         case RENDERPATH_GL13:
1925                 R_Mesh_TexBind(0, 0);
1926                 R_Mesh_TexBind(1, 0);
1927                 break;
1928         case RENDERPATH_GL11:
1929                 R_Mesh_TexBind(0, 0);
1930                 break;
1931         case RENDERPATH_SOFT:
1932                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1933                 break;
1934         }
1935 }
1936
1937 void R_SetupShader_ShowDepth(void)
1938 {
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTHLSL
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1955                 break;
1956         case RENDERPATH_GL13:
1957                 break;
1958         case RENDERPATH_GL11:
1959                 break;
1960         case RENDERPATH_SOFT:
1961                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1962                 break;
1963         }
1964 }
1965
1966 extern qboolean r_shadow_usingdeferredprepass;
1967 extern cvar_t r_shadow_deferred_8bitrange;
1968 extern rtexture_t *r_shadow_attenuationgradienttexture;
1969 extern rtexture_t *r_shadow_attenuation2dtexture;
1970 extern rtexture_t *r_shadow_attenuation3dtexture;
1971 extern qboolean r_shadow_usingshadowmap2d;
1972 extern qboolean r_shadow_usingshadowmaportho;
1973 extern float r_shadow_shadowmap_texturescale[2];
1974 extern float r_shadow_shadowmap_parameters[4];
1975 extern qboolean r_shadow_shadowmapvsdct;
1976 extern qboolean r_shadow_shadowmapsampler;
1977 extern int r_shadow_shadowmappcf;
1978 extern rtexture_t *r_shadow_shadowmap2dtexture;
1979 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1980 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1981 extern matrix4x4_t r_shadow_shadowmapmatrix;
1982 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1983 extern int r_shadow_prepass_width;
1984 extern int r_shadow_prepass_height;
1985 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1986 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1987 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1988 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1989 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1990 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
1991 {
1992         // a blendfunc allows colormod if:
1993         // a) it can never keep the destination pixel invariant, or
1994         // b) it can keep the destination pixel invariant, and still can do so if colormodded
1995         // this is to prevent unintended side effects from colormod
1996
1997         // in formulas:
1998         // IF there is a (s, sa) for which for all (d, da),
1999         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2000         // THEN, for this (s, sa) and all (colormod, d, da):
2001         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
2002         // OBVIOUSLY, this means that
2003         //   s*colormod * src(s*colormod, d, sa, da) = 0
2004         //   dst(s*colormod, d, sa, da)              = 1
2005
2006         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
2007
2008         // main condition to leave dst color invariant:
2009         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2010         //   src == GL_ZERO:
2011         //     s * 0 + d * dst(s, d, sa, da) == d
2012         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2013         //       => colormod is a problem for GL_SRC_COLOR only
2014         //   src == GL_ONE:
2015         //     s + d * dst(s, d, sa, da) == d
2016         //       => s == 0
2017         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2018         //       => colormod is never problematic for these
2019         //   src == GL_SRC_COLOR:
2020         //     s*s + d * dst(s, d, sa, da) == d
2021         //       => s == 0
2022         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2023         //       => colormod is never problematic for these
2024         //   src == GL_ONE_MINUS_SRC_COLOR:
2025         //     s*(1-s) + d * dst(s, d, sa, da) == d
2026         //       => s == 0 or s == 1
2027         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2028         //       => colormod is a problem for GL_SRC_COLOR only
2029         //   src == GL_DST_COLOR
2030         //     s*d + d * dst(s, d, sa, da) == d
2031         //       => s == 1
2032         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2033         //       => colormod is always a problem
2034         //     or
2035         //       => s == 0
2036         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2037         //       => colormod is never problematic for these
2038         //       => BUT, we do not know s! We must assume it is problematic
2039         //       then... except in GL_ONE case, where we know all invariant
2040         //       cases are fine
2041         //   src == GL_ONE_MINUS_DST_COLOR
2042         //     s*(1-d) + d * dst(s, d, sa, da) == d
2043         //       => s == 0 (1-d is impossible to handle for our desired result)
2044         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2045         //       => colormod is never problematic for these
2046         //   src == GL_SRC_ALPHA
2047         //     s*sa + d * dst(s, d, sa, da) == d
2048         //       => s == 0, or sa == 0
2049         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2050         //       => colormod breaks in the case GL_SRC_COLOR only
2051         //   src == GL_ONE_MINUS_SRC_ALPHA
2052         //     s*(1-sa) + d * dst(s, d, sa, da) == d
2053         //       => s == 0, or sa == 1
2054         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2055         //       => colormod breaks in the case GL_SRC_COLOR only
2056         //   src == GL_DST_ALPHA
2057         //     s*da + d * dst(s, d, sa, da) == d
2058         //       => s == 0
2059         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2060         //       => colormod is never problematic for these
2061
2062         switch(src)
2063         {
2064                 case GL_ZERO:
2065                 case GL_ONE_MINUS_SRC_COLOR:
2066                 case GL_SRC_ALPHA:
2067                 case GL_ONE_MINUS_SRC_ALPHA:
2068                         if(dst == GL_SRC_COLOR)
2069                                 return false;
2070                         return true;
2071                 case GL_ONE:
2072                 case GL_SRC_COLOR:
2073                 case GL_ONE_MINUS_DST_COLOR:
2074                 case GL_DST_ALPHA:
2075                 case GL_ONE_MINUS_DST_ALPHA:
2076                         return true;
2077                 case GL_DST_COLOR:
2078                         if(dst == GL_ONE)
2079                                 return true;
2080                         return false;
2081                 default:
2082                         return false;
2083         }
2084 }
2085 static qboolean R_BlendFuncAllowsFog(int src, int dst)
2086 {
2087         // a blendfunc allows fog if:
2088         // a) it can never keep the destination pixel invariant, or
2089         // b) it can keep the destination pixel invariant, and still can do so if fogged
2090         // this is to prevent unintended side effects from colormod
2091
2092         // main condition to leave dst color invariant:
2093         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2094         //   src == GL_ZERO:
2095         //     s * 0 + d * dst(s, d, sa, da) == d
2096         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2097         //       => fog is a problem for GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR only
2098         //   src == GL_ONE:
2099         //     s + d * dst(s, d, sa, da) == d
2100         //       => s == 0
2101         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2102         //       => fog is a problem for all of them, because we require s == 0
2103         //   src == GL_SRC_COLOR:
2104         //     s*s + d * dst(s, d, sa, da) == d
2105         //       => s == 0
2106         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2107         //       => fog is a problem for all of them, because we require s == 0
2108         //   src == GL_ONE_MINUS_SRC_COLOR:
2109         //     s*(1-s) + d * dst(s, d, sa, da) == d
2110         //       => s == 0 or s == 1
2111         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2112         //       => fog is a problem for all of them, because we require s == 0 or s == 1
2113         //   src == GL_DST_COLOR
2114         //     s*d + d * dst(s, d, sa, da) == d
2115         //       => s == 1
2116         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2117         //       => fog is a problem for all of them, because we require s == 1
2118         //     or
2119         //       => s == 0
2120         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2121         //       => colormod is never problematic for these
2122         //       => BUT, we do not know s! We must assume it is problematic
2123         //       then... except in GL_ONE case, where we know all invariant
2124         //       cases are fine
2125         //       => fog is a problem for all of them, because we require s == 0 or s == 1
2126         //   src == GL_ONE_MINUS_DST_COLOR
2127         //     s*(1-d) + d * dst(s, d, sa, da) == d
2128         //       => s == 0 (1-d is impossible to handle for our desired result)
2129         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2130         //       => colormod is never problematic for these
2131         //       => fog is a problem for all of them, because we require s == 0
2132         //   src == GL_SRC_ALPHA
2133         //     s*sa + d * dst(s, d, sa, da) == d
2134         //       => s == 0, or sa == 0
2135         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2136         //       => fog breaks in the case GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR only
2137         //   src == GL_ONE_MINUS_SRC_ALPHA
2138         //     s*(1-sa) + d * dst(s, d, sa, da) == d
2139         //       => s == 0, or sa == 1
2140         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2141         //       => colormod breaks in the case GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR only
2142         //   src == GL_DST_ALPHA
2143         //     s*da + d * dst(s, d, sa, da) == d
2144         //       => s == 0
2145         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2146         //       => fog is a problem for all of them, because we require s == 0
2147
2148         switch(src)
2149         {
2150                 case GL_ZERO:
2151                 case GL_SRC_ALPHA:
2152                 case GL_ONE_MINUS_SRC_ALPHA:
2153                         if(dst == GL_SRC_COLOR || dst == GL_ONE_MINUS_SRC_COLOR)
2154                                 return false;
2155                         return true;
2156                 case GL_ONE_MINUS_SRC_COLOR:
2157                 case GL_ONE_MINUS_DST_COLOR:
2158                         if(dst == GL_ONE || dst == GL_SRC_COLOR || dst == GL_ONE_MINUS_SRC_COLOR || dst == GL_SRC_ALPHA || dst == GL_ONE_MINUS_SRC_ALPHA)
2159                                 return false;
2160                         return true;
2161                 case GL_ONE:
2162                 case GL_SRC_COLOR:
2163                 case GL_DST_ALPHA:
2164                         if(dst == GL_ONE || dst == GL_ONE_MINUS_SRC_COLOR || dst == GL_SRC_ALPHA || dst == GL_ONE_MINUS_SRC_ALPHA)
2165                                 return false;
2166                         return true;
2167                 case GL_DST_COLOR:
2168                         if(dst == GL_ZERO || dst == GL_ONE_MINUS_SRC_COLOR || dst == GL_SRC_ALPHA || dst == GL_ONE_MINUS_SRC_ALPHA)
2169                                 return false;
2170                         return true;
2171                 case GL_ONE_MINUS_DST_ALPHA:
2172                         return true;
2173                 default:
2174                         return false;
2175         }
2176 }
2177 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)
2178 {
2179         // select a permutation of the lighting shader appropriate to this
2180         // combination of texture, entity, light source, and fogging, only use the
2181         // minimum features necessary to avoid wasting rendering time in the
2182         // fragment shader on features that are not being used
2183         unsigned int permutation = 0;
2184         unsigned int mode = 0;
2185         qboolean allow_colormod;
2186         qboolean allow_fog;
2187         static float dummy_colormod[3] = {1, 1, 1};
2188         float *colormod = rsurface.colormod;
2189         float m16f[16];
2190         matrix4x4_t tempmatrix;
2191         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2192         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2193                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2194         if (rsurfacepass == RSURFPASS_BACKGROUND)
2195         {
2196                 // distorted background
2197                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2198                 {
2199                         mode = SHADERMODE_WATER;
2200                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2201                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2202                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2203                         {
2204                                 // this is the right thing to do for wateralpha
2205                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2206                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2207                                 allow_fog = R_BlendFuncAllowsFog(GL_ONE, GL_ZERO);
2208                         }
2209                         else
2210                         {
2211                                 // this is the right thing to do for entity alpha
2212                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2213                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2214                                 allow_fog = R_BlendFuncAllowsFog(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2215                         }
2216                 }
2217                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2218                 {
2219                         mode = SHADERMODE_REFRACTION;
2220                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2222                         allow_fog = R_BlendFuncAllowsFog(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2223                 }
2224                 else
2225                 {
2226                         mode = SHADERMODE_GENERIC;
2227                         permutation |= SHADERPERMUTATION_DIFFUSE;
2228                         GL_BlendFunc(GL_ONE, GL_ZERO);
2229                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2230                         allow_fog = R_BlendFuncAllowsFog(GL_ONE, GL_ZERO);
2231                 }
2232         }
2233         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2234         {
2235                 if (r_glsl_offsetmapping.integer)
2236                 {
2237                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2238                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2239                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2240                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2241                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2242                         {
2243                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2244                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2245                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2246                         }
2247                 }
2248                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2249                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2250                 // normalmap (deferred prepass), may use alpha test on diffuse
2251                 mode = SHADERMODE_DEFERREDGEOMETRY;
2252                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254                 GL_BlendFunc(GL_ONE, GL_ZERO);
2255                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2256                 allow_fog = R_BlendFuncAllowsFog(GL_ONE, GL_ZERO);
2257         }
2258         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2259         {
2260                 if (r_glsl_offsetmapping.integer)
2261                 {
2262                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2263                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2264                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2265                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2266                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2267                         {
2268                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2269                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2270                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2271                         }
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275                 // light source
2276                 mode = SHADERMODE_LIGHTSOURCE;
2277                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2280                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2281                 if (diffusescale > 0)
2282                         permutation |= SHADERPERMUTATION_DIFFUSE;
2283                 if (specularscale > 0)
2284                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2285                 if (r_refdef.fogenabled)
2286                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2287                 if (rsurface.texture->colormapping)
2288                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2289                 if (r_shadow_usingshadowmap2d)
2290                 {
2291                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2292                         if(r_shadow_shadowmapvsdct)
2293                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2294
2295                         if (r_shadow_shadowmapsampler)
2296                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2297                         if (r_shadow_shadowmappcf > 1)
2298                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2299                         else if (r_shadow_shadowmappcf)
2300                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2301                 }
2302                 if (rsurface.texture->reflectmasktexture)
2303                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2304                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2305                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
2306                 allow_fog = R_BlendFuncAllowsFog(GL_SRC_ALPHA, GL_ONE);
2307         }
2308         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2309         {
2310                 if (r_glsl_offsetmapping.integer)
2311                 {
2312                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2313                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2314                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2315                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2316                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2317                         {
2318                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2319                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2320                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2321                         }
2322                 }
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325                 // unshaded geometry (fullbright or ambient model lighting)
2326                 mode = SHADERMODE_FLATCOLOR;
2327                 ambientscale = diffusescale = specularscale = 0;
2328                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2329                         permutation |= SHADERPERMUTATION_GLOW;
2330                 if (r_refdef.fogenabled)
2331                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2332                 if (rsurface.texture->colormapping)
2333                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2334                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2335                 {
2336                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2337                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2338
2339                         if (r_shadow_shadowmapsampler)
2340                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2341                         if (r_shadow_shadowmappcf > 1)
2342                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2343                         else if (r_shadow_shadowmappcf)
2344                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2345                 }
2346                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2347                         permutation |= SHADERPERMUTATION_REFLECTION;
2348                 if (rsurface.texture->reflectmasktexture)
2349                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2351                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352                 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353         }
2354         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2355         {
2356                 if (r_glsl_offsetmapping.integer)
2357                 {
2358                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2359                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2360                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2361                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2362                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2363                         {
2364                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2365                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2366                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2367                         }
2368                 }
2369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2370                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2371                 // directional model lighting
2372                 mode = SHADERMODE_LIGHTDIRECTION;
2373                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2374                         permutation |= SHADERPERMUTATION_GLOW;
2375                 permutation |= SHADERPERMUTATION_DIFFUSE;
2376                 if (specularscale > 0)
2377                         permutation |= SHADERPERMUTATION_SPECULAR;
2378                 if (r_refdef.fogenabled)
2379                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2380                 if (rsurface.texture->colormapping)
2381                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2382                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2383                 {
2384                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2385                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2386
2387                         if (r_shadow_shadowmapsampler)
2388                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2389                         if (r_shadow_shadowmappcf > 1)
2390                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2391                         else if (r_shadow_shadowmappcf)
2392                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2393                 }
2394                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2395                         permutation |= SHADERPERMUTATION_REFLECTION;
2396                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2397                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2398                 if (rsurface.texture->reflectmasktexture)
2399                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2400                 if (r_shadow_bouncegridtexture)
2401                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404                 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2405         }
2406         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2407         {
2408                 if (r_glsl_offsetmapping.integer)
2409                 {
2410                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2411                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2412                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2413                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2414                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2415                         {
2416                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2417                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2418                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2419                         }
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2422                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2423                 // ambient model lighting
2424                 mode = SHADERMODE_LIGHTDIRECTION;
2425                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2426                         permutation |= SHADERPERMUTATION_GLOW;
2427                 if (r_refdef.fogenabled)
2428                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2429                 if (rsurface.texture->colormapping)
2430                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2431                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2432                 {
2433                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2434                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2435
2436                         if (r_shadow_shadowmapsampler)
2437                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2438                         if (r_shadow_shadowmappcf > 1)
2439                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2440                         else if (r_shadow_shadowmappcf)
2441                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2442                 }
2443                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2444                         permutation |= SHADERPERMUTATION_REFLECTION;
2445                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2446                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2447                 if (rsurface.texture->reflectmasktexture)
2448                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2449                 if (r_shadow_bouncegridtexture)
2450                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2451                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2452                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2453                 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2454         }
2455         else
2456         {
2457                 if (r_glsl_offsetmapping.integer)
2458                 {
2459                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2461                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2462                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2463                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2464                         {
2465                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2466                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2467                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2468                         }
2469                 }
2470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2471                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2472                 // lightmapped wall
2473                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2474                         permutation |= SHADERPERMUTATION_GLOW;
2475                 if (r_refdef.fogenabled)
2476                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2477                 if (rsurface.texture->colormapping)
2478                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2479                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2480                 {
2481                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2482                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2483
2484                         if (r_shadow_shadowmapsampler)
2485                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2486                         if (r_shadow_shadowmappcf > 1)
2487                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2488                         else if (r_shadow_shadowmappcf)
2489                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2490                 }
2491                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2492                         permutation |= SHADERPERMUTATION_REFLECTION;
2493                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2494                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2495                 if (rsurface.texture->reflectmasktexture)
2496                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2497                 if (FAKELIGHT_ENABLED)
2498                 {
2499                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2500                         mode = SHADERMODE_FAKELIGHT;
2501                         permutation |= SHADERPERMUTATION_DIFFUSE;
2502                         if (specularscale > 0)
2503                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2504                 }
2505                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2506                 {
2507                         // deluxemapping (light direction texture)
2508                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2509                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2510                         else
2511                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2512                         permutation |= SHADERPERMUTATION_DIFFUSE;
2513                         if (specularscale > 0)
2514                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2515                 }
2516                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2517                 {
2518                         // fake deluxemapping (uniform light direction in tangentspace)
2519                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2520                         permutation |= SHADERPERMUTATION_DIFFUSE;
2521                         if (specularscale > 0)
2522                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2523                 }
2524                 else if (rsurface.uselightmaptexture)
2525                 {
2526                         // ordinary lightmapping (q1bsp, q3bsp)
2527                         mode = SHADERMODE_LIGHTMAP;
2528                 }
2529                 else
2530                 {
2531                         // ordinary vertex coloring (q3bsp)
2532                         mode = SHADERMODE_VERTEXCOLOR;
2533                 }
2534                 if (r_shadow_bouncegridtexture)
2535                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2536                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2537                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2538                 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2539         }
2540         if(!allow_colormod)
2541                 colormod = dummy_colormod;
2542         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2543                 allow_fog = allow_colormod; // we actually implement fog by colormodding with a color (f,f,f) for some f
2544         if(!allow_fog)
2545                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2546         switch(vid.renderpath)
2547         {
2548         case RENDERPATH_D3D9:
2549 #ifdef SUPPORTD3D
2550                 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);
2551                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2552                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2553                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2554                 if (mode == SHADERMODE_LIGHTSOURCE)
2555                 {
2556                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2557                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2558                 }
2559                 else
2560                 {
2561                         if (mode == SHADERMODE_LIGHTDIRECTION)
2562                         {
2563                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2564                         }
2565                 }
2566                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2567                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2568                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2569                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2570                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2571
2572                 if (mode == SHADERMODE_LIGHTSOURCE)
2573                 {
2574                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2575                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2576                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2577                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2578                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2579
2580                         // additive passes are only darkened by fog, not tinted
2581                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2582                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2583                 }
2584                 else
2585                 {
2586                         if (mode == SHADERMODE_FLATCOLOR)
2587                         {
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2589                         }
2590                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2591                         {
2592                                 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]);
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2594                                 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);
2595                                 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);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2599                         }
2600                         else
2601                         {
2602                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2603                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2604                                 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);
2605                                 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);
2606                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2607                         }
2608                         // additive passes are only darkened by fog, not tinted
2609                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2611                         else
2612                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2613                         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);
2614                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2615                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2616                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2617                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2618                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2619                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2620                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2621                         if (mode == SHADERMODE_WATER)
2622                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2623                 }
2624                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2626                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2627                 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));
2628                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2629                 if (rsurface.texture->pantstexture)
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2631                 else
2632                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2633                 if (rsurface.texture->shirttexture)
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2635                 else
2636                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2637                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2638                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2639                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2640                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2641                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2642                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2643                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2644
2645                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2646                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2647                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2648                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2649                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2650                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2651                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2652                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2653                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2654                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2655                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2656                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2657                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2658                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2659                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2660                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2661                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2662                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2663                 {
2664                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2665                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2666                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2667                 }
2668                 else
2669                 {
2670                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2671                 }
2672 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2673 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2674                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2675                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2676                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2677                 {
2678                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2679                         if (rsurface.rtlight)
2680                         {
2681                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2682                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2683                         }
2684                 }
2685 #endif
2686                 break;
2687         case RENDERPATH_D3D10:
2688                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2689                 break;
2690         case RENDERPATH_D3D11:
2691                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2692                 break;
2693         case RENDERPATH_GL20:
2694         case RENDERPATH_GLES2:
2695                 if (!vid.useinterleavedarrays)
2696                 {
2697                         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);
2698                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2699                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2700                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2701                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2702                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2703                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2704                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2705                 }
2706                 else
2707                 {
2708                         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);
2709                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2710                 }
2711                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2712                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2713                 if (mode == SHADERMODE_LIGHTSOURCE)
2714                 {
2715                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2716                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2717                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2718                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2719                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2720                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2721         
2722                         // additive passes are only darkened by fog, not tinted
2723                         if (r_glsl_permutation->loc_FogColor >= 0)
2724                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2725                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2726                 }
2727                 else
2728                 {
2729                         if (mode == SHADERMODE_FLATCOLOR)
2730                         {
2731                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2732                         }
2733                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2734                         {
2735                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2736                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2737                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(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);
2738                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(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);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2740                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2741                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2742                         }
2743                         else
2744                         {
2745                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2746                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2747                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(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);
2748                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(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);
2749                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2750                         }
2751                         // additive passes are only darkened by fog, not tinted
2752                         if (r_glsl_permutation->loc_FogColor >= 0)
2753                         {
2754                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2755                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2756                                 else
2757                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2758                         }
2759                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(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);
2760                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2761                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2762                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(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]);
2763                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(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]);
2764                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2765                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2766                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2767                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2768                 }
2769                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2770                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2771                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2772                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2773                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(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]);
2774
2775                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2776                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(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));
2777                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2778                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2779                 {
2780                         if (rsurface.texture->pantstexture)
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2782                         else
2783                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2784                 }
2785                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2786                 {
2787                         if (rsurface.texture->shirttexture)
2788                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2789                         else
2790                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2791                 }
2792                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2793                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2794                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2795                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2796                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2797                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2798                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2799                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2800                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2801
2802                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2803                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2804                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2805                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2806                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2807                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2808                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2811                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2812                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2813                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2814                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2815                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2816                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2817                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2818                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2819                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2820                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2821                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2822                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2823                 {
2824                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2825                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2826                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2827                 }
2828                 else
2829                 {
2830                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2831                 }
2832                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2833                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2834                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2835                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2836                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2837                 {
2838                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2839                         if (rsurface.rtlight)
2840                         {
2841                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2842                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2843                         }
2844                 }
2845                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2846                 CHECKGLERROR
2847                 break;
2848         case RENDERPATH_GL13:
2849         case RENDERPATH_GL11:
2850                 break;
2851         case RENDERPATH_SOFT:
2852                 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);
2853                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2854                 R_SetupShader_SetPermutationSoft(mode, permutation);
2855                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2856                 if (mode == SHADERMODE_LIGHTSOURCE)
2857                 {
2858                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2864         
2865                         // additive passes are only darkened by fog, not tinted
2866                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2867                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2868                 }
2869                 else
2870                 {
2871                         if (mode == SHADERMODE_FLATCOLOR)
2872                         {
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2874                         }
2875                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2876                         {
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2884                         }
2885                         else
2886                         {
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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);
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_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);
2891                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2892                         }
2893                         // additive passes are only darkened by fog, not tinted
2894                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2896                         else
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2898                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_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);
2899                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2900                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2901                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2904                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2905                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2906                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2907                 }
2908                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2909                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2910                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2911                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2912                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2913
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2916                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2917                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2918                 {
2919                         if (rsurface.texture->pantstexture)
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2921                         else
2922                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2923                 }
2924                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2925                 {
2926                         if (rsurface.texture->shirttexture)
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2928                         else
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2930                 }
2931                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2934                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2935                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2936                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2937                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2938
2939                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2940                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2941                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2942                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2943                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2944                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2945                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2946                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2947                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2948                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2949                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2950                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2951                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2952                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2953                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2954                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2955                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2956                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2957                 {
2958                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2959                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2960                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2961                 }
2962                 else
2963                 {
2964                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2965                 }
2966 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2967 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2968                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2969                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2970                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2971                 {
2972                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2973                         if (rsurface.rtlight)
2974                         {
2975                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2976                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2977                         }
2978                 }
2979                 break;
2980         }
2981 }
2982
2983 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2984 {
2985         // select a permutation of the lighting shader appropriate to this
2986         // combination of texture, entity, light source, and fogging, only use the
2987         // minimum features necessary to avoid wasting rendering time in the
2988         // fragment shader on features that are not being used
2989         unsigned int permutation = 0;
2990         unsigned int mode = 0;
2991         const float *lightcolorbase = rtlight->currentcolor;
2992         float ambientscale = rtlight->ambientscale;
2993         float diffusescale = rtlight->diffusescale;
2994         float specularscale = rtlight->specularscale;
2995         // this is the location of the light in view space
2996         vec3_t viewlightorigin;
2997         // this transforms from view space (camera) to light space (cubemap)
2998         matrix4x4_t viewtolight;
2999         matrix4x4_t lighttoview;
3000         float viewtolight16f[16];
3001         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3002         // light source
3003         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3004         if (rtlight->currentcubemap != r_texture_whitecube)
3005                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3006         if (diffusescale > 0)
3007                 permutation |= SHADERPERMUTATION_DIFFUSE;
3008         if (specularscale > 0)
3009                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3010         if (r_shadow_usingshadowmap2d)
3011         {
3012                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3013                 if (r_shadow_shadowmapvsdct)
3014                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3015
3016                 if (r_shadow_shadowmapsampler)
3017                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3018                 if (r_shadow_shadowmappcf > 1)
3019                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3020                 else if (r_shadow_shadowmappcf)
3021                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3022         }
3023         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3024         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3025         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3026         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3027         switch(vid.renderpath)
3028         {
3029         case RENDERPATH_D3D9:
3030 #ifdef SUPPORTD3D
3031                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3032                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3037                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3039                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3040                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3042
3043                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3044                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050                 break;
3051         case RENDERPATH_D3D10:
3052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_D3D11:
3055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_GL20:
3058         case RENDERPATH_GLES2:
3059                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3063                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3064                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3065                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3066                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       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]);
3067                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       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));
3068                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3069                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070
3071                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3073                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3074                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3075                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3076                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3077                 break;
3078         case RENDERPATH_GL13:
3079         case RENDERPATH_GL11:
3080                 break;
3081         case RENDERPATH_SOFT:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3088                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3089                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3090                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3091                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3096                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3097                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3098                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3099                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3100                 break;
3101         }
3102 }
3103
3104 #define SKINFRAME_HASH 1024
3105
3106 typedef struct
3107 {
3108         int loadsequence; // incremented each level change
3109         memexpandablearray_t array;
3110         skinframe_t *hash[SKINFRAME_HASH];
3111 }
3112 r_skinframe_t;
3113 r_skinframe_t r_skinframe;
3114
3115 void R_SkinFrame_PrepareForPurge(void)
3116 {
3117         r_skinframe.loadsequence++;
3118         // wrap it without hitting zero
3119         if (r_skinframe.loadsequence >= 200)
3120                 r_skinframe.loadsequence = 1;
3121 }
3122
3123 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3124 {
3125         if (!skinframe)
3126                 return;
3127         // mark the skinframe as used for the purging code
3128         skinframe->loadsequence = r_skinframe.loadsequence;
3129 }
3130
3131 void R_SkinFrame_Purge(void)
3132 {
3133         int i;
3134         skinframe_t *s;
3135         for (i = 0;i < SKINFRAME_HASH;i++)
3136         {
3137                 for (s = r_skinframe.hash[i];s;s = s->next)
3138                 {
3139                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3140                         {
3141                                 if (s->merged == s->base)
3142                                         s->merged = NULL;
3143                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3144                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3145                                 R_PurgeTexture(s->merged);s->merged = NULL;
3146                                 R_PurgeTexture(s->base  );s->base   = NULL;
3147                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3148                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3149                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3150                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3151                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3152                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3153                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3154                                 s->loadsequence = 0;
3155                         }
3156                 }
3157         }
3158 }
3159
3160 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3161         skinframe_t *item;
3162         char basename[MAX_QPATH];
3163
3164         Image_StripImageExtension(name, basename, sizeof(basename));
3165
3166         if( last == NULL ) {
3167                 int hashindex;
3168                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3169                 item = r_skinframe.hash[hashindex];
3170         } else {
3171                 item = last->next;
3172         }
3173
3174         // linearly search through the hash bucket
3175         for( ; item ; item = item->next ) {
3176                 if( !strcmp( item->basename, basename ) ) {
3177                         return item;
3178                 }
3179         }
3180         return NULL;
3181 }
3182
3183 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3184 {
3185         skinframe_t *item;
3186         int hashindex;
3187         char basename[MAX_QPATH];
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3192         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3193                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3194                         break;
3195
3196         if (!item) {
3197                 rtexture_t *dyntexture;
3198                 // check whether its a dynamic texture
3199                 dyntexture = CL_GetDynTexture( basename );
3200                 if (!add && !dyntexture)
3201                         return NULL;
3202                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3203                 memset(item, 0, sizeof(*item));
3204                 strlcpy(item->basename, basename, sizeof(item->basename));
3205                 item->base = dyntexture; // either NULL or dyntexture handle
3206                 item->textureflags = textureflags;
3207                 item->comparewidth = comparewidth;
3208                 item->compareheight = compareheight;
3209                 item->comparecrc = comparecrc;
3210                 item->next = r_skinframe.hash[hashindex];
3211                 r_skinframe.hash[hashindex] = item;
3212         }
3213         else if( item->base == NULL )
3214         {
3215                 rtexture_t *dyntexture;
3216                 // check whether its a dynamic texture
3217                 // 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]
3218                 dyntexture = CL_GetDynTexture( basename );
3219                 item->base = dyntexture; // either NULL or dyntexture handle
3220         }
3221
3222         R_SkinFrame_MarkUsed(item);
3223         return item;
3224 }
3225
3226 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3227         { \
3228                 unsigned long long avgcolor[5], wsum; \
3229                 int pix, comp, w; \
3230                 avgcolor[0] = 0; \
3231                 avgcolor[1] = 0; \
3232                 avgcolor[2] = 0; \
3233                 avgcolor[3] = 0; \
3234                 avgcolor[4] = 0; \
3235                 wsum = 0; \
3236                 for(pix = 0; pix < cnt; ++pix) \
3237                 { \
3238                         w = 0; \
3239                         for(comp = 0; comp < 3; ++comp) \
3240                                 w += getpixel; \
3241                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3242                         { \
3243                                 ++wsum; \
3244                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3245                                 w = getpixel; \
3246                                 for(comp = 0; comp < 3; ++comp) \
3247                                         avgcolor[comp] += getpixel * w; \
3248                                 avgcolor[3] += w; \
3249                         } \
3250                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3251                         avgcolor[4] += getpixel; \
3252                 } \
3253                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3254                         avgcolor[3] = 1; \
3255                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3256                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3257                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3258                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3259         }
3260
3261 extern cvar_t gl_picmip;
3262 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3263 {
3264         int j;
3265         unsigned char *pixels;
3266         unsigned char *bumppixels;
3267         unsigned char *basepixels = NULL;
3268         int basepixels_width = 0;
3269         int basepixels_height = 0;
3270         skinframe_t *skinframe;
3271         rtexture_t *ddsbase = NULL;
3272         qboolean ddshasalpha = false;
3273         float ddsavgcolor[4];
3274         char basename[MAX_QPATH];
3275         int miplevel = R_PicmipForFlags(textureflags);
3276         int savemiplevel = miplevel;
3277         int mymiplevel;
3278
3279         if (cls.state == ca_dedicated)
3280                 return NULL;
3281
3282         // return an existing skinframe if already loaded
3283         // if loading of the first image fails, don't make a new skinframe as it
3284         // would cause all future lookups of this to be missing
3285         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3286         if (skinframe && skinframe->base)
3287                 return skinframe;
3288
3289         Image_StripImageExtension(name, basename, sizeof(basename));
3290
3291         // check for DDS texture file first
3292         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3293         {
3294                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3295                 if (basepixels == NULL)
3296                         return NULL;
3297         }
3298
3299         // FIXME handle miplevel
3300
3301         if (developer_loading.integer)
3302                 Con_Printf("loading skin \"%s\"\n", name);
3303
3304         // we've got some pixels to store, so really allocate this new texture now
3305         if (!skinframe)
3306                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3307         skinframe->stain = NULL;
3308         skinframe->merged = NULL;
3309         skinframe->base = NULL;
3310         skinframe->pants = NULL;
3311         skinframe->shirt = NULL;
3312         skinframe->nmap = NULL;
3313         skinframe->gloss = NULL;
3314         skinframe->glow = NULL;
3315         skinframe->fog = NULL;
3316         skinframe->reflect = NULL;
3317         skinframe->hasalpha = false;
3318
3319         if (ddsbase)
3320         {
3321                 skinframe->base = ddsbase;
3322                 skinframe->hasalpha = ddshasalpha;
3323                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3324                 if (r_loadfog && skinframe->hasalpha)
3325                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3326                 //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]);
3327         }
3328         else
3329         {
3330                 basepixels_width = image_width;
3331                 basepixels_height = image_height;
3332                 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);
3333                 if (textureflags & TEXF_ALPHA)
3334                 {
3335                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3336                         {
3337                                 if (basepixels[j] < 255)
3338                                 {
3339                                         skinframe->hasalpha = true;
3340                                         break;
3341                                 }
3342                         }
3343                         if (r_loadfog && skinframe->hasalpha)
3344                         {
3345                                 // has transparent pixels
3346                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3347                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3348                                 {
3349                                         pixels[j+0] = 255;
3350                                         pixels[j+1] = 255;
3351                                         pixels[j+2] = 255;
3352                                         pixels[j+3] = basepixels[j+3];
3353                                 }
3354                                 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);
3355                                 Mem_Free(pixels);
3356                         }
3357                 }
3358                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3359                 //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]);
3360                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3361                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3362                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3363                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3364         }
3365
3366         if (r_loaddds)
3367         {
3368                 mymiplevel = savemiplevel;
3369                 if (r_loadnormalmap)
3370                         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);
3371                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3372                 if (r_loadgloss)
3373                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3374                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3375                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3376                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3377         }
3378
3379         // _norm is the name used by tenebrae and has been adopted as standard
3380         if (r_loadnormalmap && skinframe->nmap == NULL)
3381         {
3382                 mymiplevel = savemiplevel;
3383                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3384                 {
3385                         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);
3386                         Mem_Free(pixels);
3387                         pixels = NULL;
3388                 }
3389                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3390                 {
3391                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3392                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3393                         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);
3394                         Mem_Free(pixels);
3395                         Mem_Free(bumppixels);
3396                 }
3397                 else if (r_shadow_bumpscale_basetexture.value > 0)
3398                 {
3399                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3400                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3401                         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);
3402                         Mem_Free(pixels);
3403                 }
3404                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3405                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3406         }
3407
3408         // _luma is supported only for tenebrae compatibility
3409         // _glow is the preferred name
3410         mymiplevel = savemiplevel;
3411         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))))
3412         {
3413                 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);
3414                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3415                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3416                 Mem_Free(pixels);pixels = NULL;
3417         }
3418
3419         mymiplevel = savemiplevel;
3420         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3421         {
3422                 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);
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3424                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3425                 Mem_Free(pixels);
3426                 pixels = NULL;
3427         }
3428
3429         mymiplevel = savemiplevel;
3430         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3431         {
3432                 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);
3433                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3434                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3435                 Mem_Free(pixels);
3436                 pixels = NULL;
3437         }
3438
3439         mymiplevel = savemiplevel;
3440         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3441         {
3442                 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);
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3444                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3445                 Mem_Free(pixels);
3446                 pixels = NULL;
3447         }
3448
3449         mymiplevel = savemiplevel;
3450         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3451         {
3452                 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);
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3454                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3455                 Mem_Free(pixels);
3456                 pixels = NULL;
3457         }
3458
3459         if (basepixels)
3460                 Mem_Free(basepixels);
3461
3462         return skinframe;
3463 }
3464
3465 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3466 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3467 {
3468         int i;
3469         unsigned char *temp1, *temp2;
3470         skinframe_t *skinframe;
3471
3472         if (cls.state == ca_dedicated)
3473                 return NULL;
3474
3475         // if already loaded just return it, otherwise make a new skinframe
3476         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3477         if (skinframe && skinframe->base)
3478                 return skinframe;
3479
3480         skinframe->stain = NULL;
3481         skinframe->merged = NULL;
3482         skinframe->base = NULL;
3483         skinframe->pants = NULL;
3484         skinframe->shirt = NULL;
3485         skinframe->nmap = NULL;
3486         skinframe->gloss = NULL;
3487         skinframe->glow = NULL;
3488         skinframe->fog = NULL;
3489         skinframe->reflect = NULL;
3490         skinframe->hasalpha = false;
3491
3492         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3493         if (!skindata)
3494                 return NULL;
3495
3496         if (developer_loading.integer)
3497                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3498
3499         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3500         {
3501                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3502                 temp2 = temp1 + width * height * 4;
3503                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3504                 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);
3505                 Mem_Free(temp1);
3506         }
3507         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3508         if (textureflags & TEXF_ALPHA)
3509         {
3510                 for (i = 3;i < width * height * 4;i += 4)
3511                 {
3512                         if (skindata[i] < 255)
3513                         {
3514                                 skinframe->hasalpha = true;
3515                                 break;
3516                         }
3517                 }
3518                 if (r_loadfog && skinframe->hasalpha)
3519                 {
3520                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3521                         memcpy(fogpixels, skindata, width * height * 4);
3522                         for (i = 0;i < width * height * 4;i += 4)
3523                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3524                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3525                         Mem_Free(fogpixels);
3526                 }
3527         }
3528
3529         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3530         //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]);
3531
3532         return skinframe;
3533 }
3534
3535 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3536 {
3537         int i;
3538         int featuresmask;
3539         skinframe_t *skinframe;
3540
3541         if (cls.state == ca_dedicated)
3542                 return NULL;
3543
3544         // if already loaded just return it, otherwise make a new skinframe
3545         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3546         if (skinframe && skinframe->base)
3547                 return skinframe;
3548
3549         skinframe->stain = NULL;
3550         skinframe->merged = NULL;
3551         skinframe->base = NULL;
3552         skinframe->pants = NULL;
3553         skinframe->shirt = NULL;
3554         skinframe->nmap = NULL;
3555         skinframe->gloss = NULL;
3556         skinframe->glow = NULL;
3557         skinframe->fog = NULL;
3558         skinframe->reflect = NULL;
3559         skinframe->hasalpha = false;
3560
3561         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3562         if (!skindata)
3563                 return NULL;
3564
3565         if (developer_loading.integer)
3566                 Con_Printf("loading quake skin \"%s\"\n", name);
3567
3568         // 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)
3569         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3570         memcpy(skinframe->qpixels, skindata, width*height);
3571         skinframe->qwidth = width;
3572         skinframe->qheight = height;
3573
3574         featuresmask = 0;
3575         for (i = 0;i < width * height;i++)
3576                 featuresmask |= palette_featureflags[skindata[i]];
3577
3578         skinframe->hasalpha = false;
3579         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3580         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3581         skinframe->qgeneratemerged = true;
3582         skinframe->qgeneratebase = skinframe->qhascolormapping;
3583         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3584
3585         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3586         //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]);
3587
3588         return skinframe;
3589 }
3590
3591 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3592 {
3593         int width;
3594         int height;
3595         unsigned char *skindata;
3596
3597         if (!skinframe->qpixels)
3598                 return;
3599
3600         if (!skinframe->qhascolormapping)
3601                 colormapped = false;
3602
3603         if (colormapped)
3604         {
3605                 if (!skinframe->qgeneratebase)
3606                         return;
3607         }
3608         else
3609         {
3610                 if (!skinframe->qgeneratemerged)
3611                         return;
3612         }
3613
3614         width = skinframe->qwidth;
3615         height = skinframe->qheight;
3616         skindata = skinframe->qpixels;
3617
3618         if (skinframe->qgeneratenmap)
3619         {
3620                 unsigned char *temp1, *temp2;
3621                 skinframe->qgeneratenmap = false;
3622                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3623                 temp2 = temp1 + width * height * 4;
3624                 // use either a custom palette or the quake palette
3625                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3626                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3627                 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);
3628                 Mem_Free(temp1);
3629         }
3630
3631         if (skinframe->qgenerateglow)
3632         {
3633                 skinframe->qgenerateglow = false;
3634                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3635         }
3636
3637         if (colormapped)
3638         {
3639                 skinframe->qgeneratebase = false;
3640                 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);
3641                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3642                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3643         }
3644         else
3645         {
3646                 skinframe->qgeneratemerged = false;
3647                 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);
3648         }
3649
3650         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3651         {
3652                 Mem_Free(skinframe->qpixels);
3653                 skinframe->qpixels = NULL;
3654         }
3655 }
3656
3657 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)
3658 {
3659         int i;
3660         skinframe_t *skinframe;
3661
3662         if (cls.state == ca_dedicated)
3663                 return NULL;
3664
3665         // if already loaded just return it, otherwise make a new skinframe
3666         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3667         if (skinframe && skinframe->base)
3668                 return skinframe;
3669
3670         skinframe->stain = NULL;
3671         skinframe->merged = NULL;
3672         skinframe->base = NULL;
3673         skinframe->pants = NULL;
3674         skinframe->shirt = NULL;
3675         skinframe->nmap = NULL;
3676         skinframe->gloss = NULL;
3677         skinframe->glow = NULL;
3678         skinframe->fog = NULL;
3679         skinframe->reflect = NULL;
3680         skinframe->hasalpha = false;
3681
3682         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3683         if (!skindata)
3684                 return NULL;
3685
3686         if (developer_loading.integer)
3687                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3688
3689         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3690         if (textureflags & TEXF_ALPHA)
3691         {
3692                 for (i = 0;i < width * height;i++)
3693                 {
3694                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3695                         {
3696                                 skinframe->hasalpha = true;
3697                                 break;
3698                         }
3699                 }
3700                 if (r_loadfog && skinframe->hasalpha)
3701                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3702         }
3703
3704         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3705         //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]);
3706
3707         return skinframe;
3708 }
3709
3710 skinframe_t *R_SkinFrame_LoadMissing(void)
3711 {
3712         skinframe_t *skinframe;
3713
3714         if (cls.state == ca_dedicated)
3715                 return NULL;
3716
3717         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3718         skinframe->stain = NULL;
3719         skinframe->merged = NULL;
3720         skinframe->base = NULL;
3721         skinframe->pants = NULL;
3722         skinframe->shirt = NULL;
3723         skinframe->nmap = NULL;
3724         skinframe->gloss = NULL;
3725         skinframe->glow = NULL;
3726         skinframe->fog = NULL;
3727         skinframe->reflect = NULL;
3728         skinframe->hasalpha = false;
3729
3730         skinframe->avgcolor[0] = rand() / RAND_MAX;
3731         skinframe->avgcolor[1] = rand() / RAND_MAX;
3732         skinframe->avgcolor[2] = rand() / RAND_MAX;
3733         skinframe->avgcolor[3] = 1;
3734
3735         return skinframe;
3736 }
3737
3738 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3739 typedef struct suffixinfo_s
3740 {
3741         const char *suffix;
3742         qboolean flipx, flipy, flipdiagonal;
3743 }
3744 suffixinfo_t;
3745 static suffixinfo_t suffix[3][6] =
3746 {
3747         {
3748                 {"px",   false, false, false},
3749                 {"nx",   false, false, false},
3750                 {"py",   false, false, false},
3751                 {"ny",   false, false, false},
3752                 {"pz",   false, false, false},
3753                 {"nz",   false, false, false}
3754         },
3755         {
3756                 {"posx", false, false, false},
3757                 {"negx", false, false, false},
3758                 {"posy", false, false, false},
3759                 {"negy", false, false, false},
3760                 {"posz", false, false, false},
3761                 {"negz", false, false, false}
3762         },
3763         {
3764                 {"rt",    true, false,  true},
3765                 {"lf",   false,  true,  true},
3766                 {"ft",    true,  true, false},
3767                 {"bk",   false, false, false},
3768                 {"up",    true, false,  true},
3769                 {"dn",    true, false,  true}
3770         }
3771 };
3772
3773 static int componentorder[4] = {0, 1, 2, 3};
3774
3775 rtexture_t *R_LoadCubemap(const char *basename)
3776 {
3777         int i, j, cubemapsize;
3778         unsigned char *cubemappixels, *image_buffer;
3779         rtexture_t *cubemaptexture;
3780         char name[256];
3781         // must start 0 so the first loadimagepixels has no requested width/height
3782         cubemapsize = 0;
3783         cubemappixels = NULL;
3784         cubemaptexture = NULL;
3785         // keep trying different suffix groups (posx, px, rt) until one loads
3786         for (j = 0;j < 3 && !cubemappixels;j++)
3787         {
3788                 // load the 6 images in the suffix group
3789                 for (i = 0;i < 6;i++)
3790                 {
3791                         // generate an image name based on the base and and suffix
3792                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3793                         // load it
3794                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3795                         {
3796                                 // an image loaded, make sure width and height are equal
3797                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3798                                 {
3799                                         // if this is the first image to load successfully, allocate the cubemap memory
3800                                         if (!cubemappixels && image_width >= 1)
3801                                         {
3802                                                 cubemapsize = image_width;
3803                                                 // note this clears to black, so unavailable sides are black
3804                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3805                                         }
3806                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3807                                         if (cubemappixels)
3808                                                 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);
3809                                 }
3810                                 else
3811                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3812                                 // free the image
3813                                 Mem_Free(image_buffer);
3814                         }
3815                 }
3816         }
3817         // if a cubemap loaded, upload it
3818         if (cubemappixels)
3819         {
3820                 if (developer_loading.integer)
3821                         Con_Printf("loading cubemap \"%s\"\n", basename);
3822
3823                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3824                 Mem_Free(cubemappixels);
3825         }
3826         else
3827         {
3828                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3829                 if (developer_loading.integer)
3830                 {
3831                         Con_Printf("(tried tried images ");
3832                         for (j = 0;j < 3;j++)
3833                                 for (i = 0;i < 6;i++)
3834                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3835                         Con_Print(" and was unable to find any of them).\n");
3836                 }
3837         }
3838         return cubemaptexture;
3839 }
3840
3841 rtexture_t *R_GetCubemap(const char *basename)
3842 {
3843         int i;
3844         for (i = 0;i < r_texture_numcubemaps;i++)
3845                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3846                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3847         if (i >= MAX_CUBEMAPS)
3848                 return r_texture_whitecube;
3849         r_texture_numcubemaps++;
3850         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3851         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3852         return r_texture_cubemaps[i].texture;
3853 }
3854
3855 void R_FreeCubemaps(void)
3856 {
3857         int i;
3858         for (i = 0;i < r_texture_numcubemaps;i++)
3859         {
3860                 if (developer_loading.integer)
3861                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3862                 if (r_texture_cubemaps[i].texture)
3863                         R_FreeTexture(r_texture_cubemaps[i].texture);
3864         }
3865         r_texture_numcubemaps = 0;
3866 }
3867
3868 void R_Main_FreeViewCache(void)
3869 {
3870         if (r_refdef.viewcache.entityvisible)
3871                 Mem_Free(r_refdef.viewcache.entityvisible);
3872         if (r_refdef.viewcache.world_pvsbits)
3873                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3874         if (r_refdef.viewcache.world_leafvisible)
3875                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3876         if (r_refdef.viewcache.world_surfacevisible)
3877                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3878         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3879 }
3880
3881 void R_Main_ResizeViewCache(void)
3882 {
3883         int numentities = r_refdef.scene.numentities;
3884         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3885         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3886         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3887         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3888         if (r_refdef.viewcache.maxentities < numentities)
3889         {
3890                 r_refdef.viewcache.maxentities = numentities;
3891                 if (r_refdef.viewcache.entityvisible)
3892                         Mem_Free(r_refdef.viewcache.entityvisible);
3893                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3894         }
3895         if (r_refdef.viewcache.world_numclusters != numclusters)
3896         {
3897                 r_refdef.viewcache.world_numclusters = numclusters;
3898                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3899                 if (r_refdef.viewcache.world_pvsbits)
3900                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3901                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3902         }
3903         if (r_refdef.viewcache.world_numleafs != numleafs)
3904         {
3905                 r_refdef.viewcache.world_numleafs = numleafs;
3906                 if (r_refdef.viewcache.world_leafvisible)
3907                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3908                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3909         }
3910         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3911         {
3912                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3913                 if (r_refdef.viewcache.world_surfacevisible)
3914                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3915                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3916         }
3917 }
3918
3919 extern rtexture_t *loadingscreentexture;
3920 void gl_main_start(void)
3921 {
3922         loadingscreentexture = NULL;
3923         r_texture_blanknormalmap = NULL;
3924         r_texture_white = NULL;
3925         r_texture_grey128 = NULL;
3926         r_texture_black = NULL;
3927         r_texture_whitecube = NULL;
3928         r_texture_normalizationcube = NULL;
3929         r_texture_fogattenuation = NULL;
3930         r_texture_fogheighttexture = NULL;
3931         r_texture_gammaramps = NULL;
3932         r_texture_numcubemaps = 0;
3933
3934         r_loaddds = r_texture_dds_load.integer != 0;
3935         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3936
3937         switch(vid.renderpath)
3938         {
3939         case RENDERPATH_GL20:
3940         case RENDERPATH_D3D9:
3941         case RENDERPATH_D3D10:
3942         case RENDERPATH_D3D11:
3943         case RENDERPATH_SOFT:
3944                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3945                 Cvar_SetValueQuick(&gl_combine, 1);
3946                 Cvar_SetValueQuick(&r_glsl, 1);
3947                 r_loadnormalmap = true;
3948                 r_loadgloss = true;
3949                 r_loadfog = false;
3950                 break;
3951         case RENDERPATH_GL13:
3952                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3953                 Cvar_SetValueQuick(&gl_combine, 1);
3954                 Cvar_SetValueQuick(&r_glsl, 0);
3955                 r_loadnormalmap = false;
3956                 r_loadgloss = false;
3957                 r_loadfog = true;
3958                 break;
3959         case RENDERPATH_GL11:
3960                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3961                 Cvar_SetValueQuick(&gl_combine, 0);
3962                 Cvar_SetValueQuick(&r_glsl, 0);
3963                 r_loadnormalmap = false;
3964                 r_loadgloss = false;
3965                 r_loadfog = true;
3966                 break;
3967         case RENDERPATH_GLES2:
3968                 Cvar_SetValueQuick(&r_textureunits, 1);
3969                 Cvar_SetValueQuick(&gl_combine, 1);
3970                 Cvar_SetValueQuick(&r_glsl, 1);
3971                 r_loadnormalmap = true;
3972                 r_loadgloss = false;
3973                 r_loadfog = false;
3974                 break;
3975         }
3976
3977         R_AnimCache_Free();
3978         R_FrameData_Reset();
3979
3980         r_numqueries = 0;
3981         r_maxqueries = 0;
3982         memset(r_queries, 0, sizeof(r_queries));
3983
3984         r_qwskincache = NULL;
3985         r_qwskincache_size = 0;
3986
3987         // set up r_skinframe loading system for textures
3988         memset(&r_skinframe, 0, sizeof(r_skinframe));
3989         r_skinframe.loadsequence = 1;
3990         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3991
3992         r_main_texturepool = R_AllocTexturePool();
3993         R_BuildBlankTextures();
3994         R_BuildNoTexture();
3995         if (vid.support.arb_texture_cube_map)
3996         {
3997                 R_BuildWhiteCube();
3998                 R_BuildNormalizationCube();
3999         }
4000         r_texture_fogattenuation = NULL;
4001         r_texture_fogheighttexture = NULL;
4002         r_texture_gammaramps = NULL;
4003         //r_texture_fogintensity = NULL;
4004         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4005         memset(&r_waterstate, 0, sizeof(r_waterstate));
4006         r_glsl_permutation = NULL;
4007         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4008         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4009         glslshaderstring = NULL;
4010 #ifdef SUPPORTD3D
4011         r_hlsl_permutation = NULL;
4012         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4013         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4014 #endif
4015         hlslshaderstring = NULL;
4016         memset(&r_svbsp, 0, sizeof (r_svbsp));
4017
4018         r_refdef.fogmasktable_density = 0;
4019 }
4020
4021 void gl_main_shutdown(void)
4022 {
4023         R_AnimCache_Free();
4024         R_FrameData_Reset();
4025
4026         R_Main_FreeViewCache();
4027
4028         switch(vid.renderpath)
4029         {
4030         case RENDERPATH_GL11:
4031         case RENDERPATH_GL13:
4032         case RENDERPATH_GL20:
4033         case RENDERPATH_GLES2:
4034                 if (r_maxqueries)
4035                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4036                 break;
4037         case RENDERPATH_D3D9:
4038                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4039                 break;
4040         case RENDERPATH_D3D10:
4041                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4042                 break;
4043         case RENDERPATH_D3D11:
4044                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4045                 break;
4046         case RENDERPATH_SOFT:
4047                 break;
4048         }
4049
4050         r_numqueries = 0;
4051         r_maxqueries = 0;
4052         memset(r_queries, 0, sizeof(r_queries));
4053
4054         r_qwskincache = NULL;
4055         r_qwskincache_size = 0;
4056
4057         // clear out the r_skinframe state
4058         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4059         memset(&r_skinframe, 0, sizeof(r_skinframe));
4060
4061         if (r_svbsp.nodes)
4062                 Mem_Free(r_svbsp.nodes);
4063         memset(&r_svbsp, 0, sizeof (r_svbsp));
4064         R_FreeTexturePool(&r_main_texturepool);
4065         loadingscreentexture = NULL;
4066         r_texture_blanknormalmap = NULL;
4067         r_texture_white = NULL;
4068         r_texture_grey128 = NULL;
4069         r_texture_black = NULL;
4070         r_texture_whitecube = NULL;
4071         r_texture_normalizationcube = NULL;
4072         r_texture_fogattenuation = NULL;
4073         r_texture_fogheighttexture = NULL;
4074         r_texture_gammaramps = NULL;
4075         r_texture_numcubemaps = 0;
4076         //r_texture_fogintensity = NULL;
4077         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4078         memset(&r_waterstate, 0, sizeof(r_waterstate));
4079         R_GLSL_Restart_f();
4080
4081         r_glsl_permutation = NULL;
4082         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4083         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4084         glslshaderstring = NULL;
4085 #ifdef SUPPORTD3D
4086         r_hlsl_permutation = NULL;
4087         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4088         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4089 #endif
4090         hlslshaderstring = NULL;
4091 }
4092
4093 extern void CL_ParseEntityLump(char *entitystring);
4094 void gl_main_newmap(void)
4095 {
4096         // FIXME: move this code to client
4097         char *entities, entname[MAX_QPATH];
4098         if (r_qwskincache)
4099                 Mem_Free(r_qwskincache);
4100         r_qwskincache = NULL;
4101         r_qwskincache_size = 0;
4102         if (cl.worldmodel)
4103         {
4104                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4105                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4106                 {
4107                         CL_ParseEntityLump(entities);
4108                         Mem_Free(entities);
4109                         return;
4110                 }
4111                 if (cl.worldmodel->brush.entities)
4112                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4113         }
4114         R_Main_FreeViewCache();
4115
4116         R_FrameData_Reset();
4117 }
4118
4119 void GL_Main_Init(void)
4120 {
4121         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4122
4123         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4124         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4125         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4126         if (gamemode == GAME_NEHAHRA)
4127         {
4128                 Cvar_RegisterVariable (&gl_fogenable);
4129                 Cvar_RegisterVariable (&gl_fogdensity);
4130                 Cvar_RegisterVariable (&gl_fogred);
4131                 Cvar_RegisterVariable (&gl_foggreen);
4132                 Cvar_RegisterVariable (&gl_fogblue);
4133                 Cvar_RegisterVariable (&gl_fogstart);
4134                 Cvar_RegisterVariable (&gl_fogend);
4135                 Cvar_RegisterVariable (&gl_skyclip);
4136         }
4137         Cvar_RegisterVariable(&r_motionblur);
4138         Cvar_RegisterVariable(&r_motionblur_maxblur);
4139         Cvar_RegisterVariable(&r_motionblur_bmin);
4140         Cvar_RegisterVariable(&r_motionblur_vmin);
4141         Cvar_RegisterVariable(&r_motionblur_vmax);
4142         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4143         Cvar_RegisterVariable(&r_motionblur_randomize);
4144         Cvar_RegisterVariable(&r_damageblur);
4145         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4146         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4147         Cvar_RegisterVariable(&r_equalize_entities_by);
4148         Cvar_RegisterVariable(&r_equalize_entities_to);
4149         Cvar_RegisterVariable(&r_depthfirst);
4150         Cvar_RegisterVariable(&r_useinfinitefarclip);
4151         Cvar_RegisterVariable(&r_farclip_base);
4152         Cvar_RegisterVariable(&r_farclip_world);
4153         Cvar_RegisterVariable(&r_nearclip);
4154         Cvar_RegisterVariable(&r_showbboxes);
4155         Cvar_RegisterVariable(&r_showsurfaces);
4156         Cvar_RegisterVariable(&r_showtris);
4157         Cvar_RegisterVariable(&r_shownormals);
4158         Cvar_RegisterVariable(&r_showlighting);
4159         Cvar_RegisterVariable(&r_showshadowvolumes);
4160         Cvar_RegisterVariable(&r_showcollisionbrushes);
4161         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4162         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4163         Cvar_RegisterVariable(&r_showdisabledepthtest);
4164         Cvar_RegisterVariable(&r_drawportals);
4165         Cvar_RegisterVariable(&r_drawentities);
4166         Cvar_RegisterVariable(&r_draw2d);
4167         Cvar_RegisterVariable(&r_drawworld);
4168         Cvar_RegisterVariable(&r_cullentities_trace);
4169         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4170         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4171         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4172         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4173         Cvar_RegisterVariable(&r_drawviewmodel);
4174         Cvar_RegisterVariable(&r_drawexteriormodel);
4175         Cvar_RegisterVariable(&r_speeds);
4176         Cvar_RegisterVariable(&r_fullbrights);
4177         Cvar_RegisterVariable(&r_wateralpha);
4178         Cvar_RegisterVariable(&r_dynamic);
4179         Cvar_RegisterVariable(&r_fakelight);
4180         Cvar_RegisterVariable(&r_fakelight_intensity);
4181         Cvar_RegisterVariable(&r_fullbright);
4182         Cvar_RegisterVariable(&r_shadows);
4183         Cvar_RegisterVariable(&r_shadows_darken);
4184         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4185         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4186         Cvar_RegisterVariable(&r_shadows_throwdistance);
4187         Cvar_RegisterVariable(&r_shadows_throwdirection);
4188         Cvar_RegisterVariable(&r_shadows_focus);
4189         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4190         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4191         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4192         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4193         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4194         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4195         Cvar_RegisterVariable(&r_fog_exp2);
4196         Cvar_RegisterVariable(&r_drawfog);
4197         Cvar_RegisterVariable(&r_transparentdepthmasking);
4198         Cvar_RegisterVariable(&r_texture_dds_load);
4199         Cvar_RegisterVariable(&r_texture_dds_save);
4200         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4201         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4202         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4203         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4204         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4205         Cvar_RegisterVariable(&r_textureunits);
4206         Cvar_RegisterVariable(&gl_combine);
4207         Cvar_RegisterVariable(&r_glsl);
4208         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4209         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4210         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4211         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4212         Cvar_RegisterVariable(&r_glsl_postprocess);
4213         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4214         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4215         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4216         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4217         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4218         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4219         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4220         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4221
4222         Cvar_RegisterVariable(&r_water);
4223         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4224         Cvar_RegisterVariable(&r_water_clippingplanebias);
4225         Cvar_RegisterVariable(&r_water_refractdistort);
4226         Cvar_RegisterVariable(&r_water_reflectdistort);
4227         Cvar_RegisterVariable(&r_water_scissormode);
4228         Cvar_RegisterVariable(&r_lerpsprites);
4229         Cvar_RegisterVariable(&r_lerpmodels);
4230         Cvar_RegisterVariable(&r_lerplightstyles);
4231         Cvar_RegisterVariable(&r_waterscroll);
4232         Cvar_RegisterVariable(&r_bloom);
4233         Cvar_RegisterVariable(&r_bloom_colorscale);
4234         Cvar_RegisterVariable(&r_bloom_brighten);
4235         Cvar_RegisterVariable(&r_bloom_blur);
4236         Cvar_RegisterVariable(&r_bloom_resolution);
4237         Cvar_RegisterVariable(&r_bloom_colorexponent);
4238         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4239         Cvar_RegisterVariable(&r_hdr);
4240         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4241         Cvar_RegisterVariable(&r_hdr_glowintensity);
4242         Cvar_RegisterVariable(&r_hdr_range);
4243         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4244         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4245         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4246         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4247         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4248         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4249         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4250         Cvar_RegisterVariable(&developer_texturelogging);
4251         Cvar_RegisterVariable(&gl_lightmaps);
4252         Cvar_RegisterVariable(&r_test);
4253         Cvar_RegisterVariable(&r_glsl_saturation);
4254         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4255         Cvar_RegisterVariable(&r_framedatasize);
4256         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4257                 Cvar_SetValue("r_fullbrights", 0);
4258         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4259
4260         Cvar_RegisterVariable(&r_track_sprites);
4261         Cvar_RegisterVariable(&r_track_sprites_flags);
4262         Cvar_RegisterVariable(&r_track_sprites_scalew);
4263         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4264         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4265         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4266         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4267         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4268 }
4269
4270 extern void R_Textures_Init(void);
4271 extern void GL_Draw_Init(void);
4272 extern void GL_Main_Init(void);
4273 extern void R_Shadow_Init(void);
4274 extern void R_Sky_Init(void);
4275 extern void GL_Surf_Init(void);
4276 extern void R_Particles_Init(void);
4277 extern void R_Explosion_Init(void);
4278 extern void gl_backend_init(void);
4279 extern void Sbar_Init(void);
4280 extern void R_LightningBeams_Init(void);
4281 extern void Mod_RenderInit(void);
4282 extern void Font_Init(void);
4283
4284 void Render_Init(void)
4285 {
4286         gl_backend_init();
4287         R_Textures_Init();
4288         GL_Main_Init();
4289         Font_Init();
4290         GL_Draw_Init();
4291         R_Shadow_Init();
4292         R_Sky_Init();
4293         GL_Surf_Init();
4294         Sbar_Init();
4295         R_Particles_Init();
4296         R_Explosion_Init();
4297         R_LightningBeams_Init();
4298         Mod_RenderInit();
4299 }
4300
4301 /*
4302 ===============
4303 GL_Init
4304 ===============
4305 */
4306 extern char *ENGINE_EXTENSIONS;
4307 void GL_Init (void)
4308 {
4309         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4310         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4311         gl_version = (const char *)qglGetString(GL_VERSION);
4312         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4313
4314         if (!gl_extensions)
4315                 gl_extensions = "";
4316         if (!gl_platformextensions)
4317                 gl_platformextensions = "";
4318
4319         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4320         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4321         Con_Printf("GL_VERSION: %s\n", gl_version);
4322         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4323         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4324
4325         VID_CheckExtensions();
4326
4327         // LordHavoc: report supported extensions
4328         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4329
4330         // clear to black (loading plaque will be seen over this)
4331         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4332 }
4333
4334 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4335 {
4336         int i;
4337         mplane_t *p;
4338         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4339         {
4340                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4341                 if (i == 4)
4342                         continue;
4343                 p = r_refdef.view.frustum + i;
4344                 switch(p->signbits)
4345                 {
4346                 default:
4347                 case 0:
4348                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4349                                 return true;
4350                         break;
4351                 case 1:
4352                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4353                                 return true;
4354                         break;
4355                 case 2:
4356                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4357                                 return true;
4358                         break;
4359                 case 3:
4360                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4361                                 return true;
4362                         break;
4363                 case 4:
4364                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4365                                 return true;
4366                         break;
4367                 case 5:
4368                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4369                                 return true;
4370                         break;
4371                 case 6:
4372                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4373                                 return true;
4374                         break;
4375                 case 7:
4376                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4377                                 return true;
4378                         break;
4379                 }
4380         }
4381         return false;
4382 }
4383
4384 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4385 {
4386         int i;
4387         const mplane_t *p;
4388         for (i = 0;i < numplanes;i++)
4389         {
4390                 p = planes + i;
4391                 switch(p->signbits)
4392                 {
4393                 default:
4394                 case 0:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 1:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 2:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 3:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 4:
4411                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 5:
4415                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 6:
4419                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 case 7:
4423                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4424                                 return true;
4425                         break;
4426                 }
4427         }
4428         return false;
4429 }
4430
4431 //==================================================================================
4432
4433 // LordHavoc: this stores temporary data used within the same frame
4434
4435 typedef struct r_framedata_mem_s
4436 {
4437         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4438         size_t size; // how much usable space
4439         size_t current; // how much space in use
4440         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4441         size_t wantedsize; // how much space was allocated
4442         unsigned char *data; // start of real data (16byte aligned)
4443 }
4444 r_framedata_mem_t;
4445
4446 static r_framedata_mem_t *r_framedata_mem;
4447
4448 void R_FrameData_Reset(void)
4449 {
4450         while (r_framedata_mem)
4451         {
4452                 r_framedata_mem_t *next = r_framedata_mem->purge;
4453                 Mem_Free(r_framedata_mem);
4454                 r_framedata_mem = next;
4455         }
4456 }
4457
4458 void R_FrameData_Resize(void)
4459 {
4460         size_t wantedsize;
4461         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4462         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4463         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4464         {
4465                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4466                 newmem->wantedsize = wantedsize;
4467                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4468                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4469                 newmem->current = 0;
4470                 newmem->mark = 0;
4471                 newmem->purge = r_framedata_mem;
4472                 r_framedata_mem = newmem;
4473         }
4474 }
4475
4476 void R_FrameData_NewFrame(void)
4477 {
4478         R_FrameData_Resize();
4479         if (!r_framedata_mem)
4480                 return;
4481         // if we ran out of space on the last frame, free the old memory now
4482         while (r_framedata_mem->purge)
4483         {
4484                 // repeatedly remove the second item in the list, leaving only head
4485                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4486                 Mem_Free(r_framedata_mem->purge);
4487                 r_framedata_mem->purge = next;
4488         }
4489         // reset the current mem pointer
4490         r_framedata_mem->current = 0;
4491         r_framedata_mem->mark = 0;
4492 }
4493
4494 void *R_FrameData_Alloc(size_t size)
4495 {
4496         void *data;
4497
4498         // align to 16 byte boundary - the data pointer is already aligned, so we
4499         // only need to ensure the size of every allocation is also aligned
4500         size = (size + 15) & ~15;
4501
4502         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4503         {
4504                 // emergency - we ran out of space, allocate more memory
4505                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4506                 R_FrameData_Resize();
4507         }
4508
4509         data = r_framedata_mem->data + r_framedata_mem->current;
4510         r_framedata_mem->current += size;
4511
4512         // count the usage for stats
4513         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4514         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4515
4516         return (void *)data;
4517 }
4518
4519 void *R_FrameData_Store(size_t size, void *data)
4520 {
4521         void *d = R_FrameData_Alloc(size);
4522         if (d && data)
4523                 memcpy(d, data, size);
4524         return d;
4525 }
4526
4527 void R_FrameData_SetMark(void)
4528 {
4529         if (!r_framedata_mem)
4530                 return;
4531         r_framedata_mem->mark = r_framedata_mem->current;
4532 }
4533
4534 void R_FrameData_ReturnToMark(void)
4535 {
4536         if (!r_framedata_mem)
4537                 return;
4538         r_framedata_mem->current = r_framedata_mem->mark;
4539 }
4540
4541 //==================================================================================
4542
4543 // LordHavoc: animcache originally written by Echon, rewritten since then
4544
4545 /**
4546  * Animation cache prevents re-generating mesh data for an animated model
4547  * multiple times in one frame for lighting, shadowing, reflections, etc.
4548  */
4549
4550 void R_AnimCache_Free(void)
4551 {
4552 }
4553
4554 void R_AnimCache_ClearCache(void)
4555 {
4556         int i;
4557         entity_render_t *ent;
4558
4559         for (i = 0;i < r_refdef.scene.numentities;i++)
4560         {
4561                 ent = r_refdef.scene.entities[i];
4562                 ent->animcache_vertex3f = NULL;
4563                 ent->animcache_normal3f = NULL;
4564                 ent->animcache_svector3f = NULL;
4565                 ent->animcache_tvector3f = NULL;
4566                 ent->animcache_vertexmesh = NULL;
4567                 ent->animcache_vertex3fbuffer = NULL;
4568                 ent->animcache_vertexmeshbuffer = NULL;
4569         }
4570 }
4571
4572 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4573 {
4574         int i;
4575
4576         // check if we need the meshbuffers
4577         if (!vid.useinterleavedarrays)
4578                 return;
4579
4580         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4581                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4582         // TODO: upload vertex3f buffer?
4583         if (ent->animcache_vertexmesh)
4584         {
4585                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4586                 for (i = 0;i < numvertices;i++)
4587                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4588                 if (ent->animcache_svector3f)
4589                         for (i = 0;i < numvertices;i++)
4590                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4591                 if (ent->animcache_tvector3f)
4592                         for (i = 0;i < numvertices;i++)
4593                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4594                 if (ent->animcache_normal3f)
4595                         for (i = 0;i < numvertices;i++)
4596                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4597                 // TODO: upload vertexmeshbuffer?
4598         }
4599 }
4600
4601 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4602 {
4603         dp_model_t *model = ent->model;
4604         int numvertices;
4605         // see if it's already cached this frame
4606         if (ent->animcache_vertex3f)
4607         {
4608                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4609                 if (wantnormals || wanttangents)
4610                 {
4611                         if (ent->animcache_normal3f)
4612                                 wantnormals = false;
4613                         if (ent->animcache_svector3f)
4614                                 wanttangents = false;
4615                         if (wantnormals || wanttangents)
4616                         {
4617                                 numvertices = model->surfmesh.num_vertices;
4618                                 if (wantnormals)
4619                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4620                                 if (wanttangents)
4621                                 {
4622                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4623                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4624                                 }
4625                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4626                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4627                         }
4628                 }
4629         }
4630         else
4631         {
4632                 // see if this ent is worth caching
4633                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4634                         return false;
4635                 // get some memory for this entity and generate mesh data
4636                 numvertices = model->surfmesh.num_vertices;
4637                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4638                 if (wantnormals)
4639                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4640                 if (wanttangents)
4641                 {
4642                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4643                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4644                 }
4645                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4646                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4647         }
4648         return true;
4649 }
4650
4651 void R_AnimCache_CacheVisibleEntities(void)
4652 {
4653         int i;
4654         qboolean wantnormals = true;
4655         qboolean wanttangents = !r_showsurfaces.integer;
4656
4657         switch(vid.renderpath)
4658         {
4659         case RENDERPATH_GL20:
4660         case RENDERPATH_D3D9:
4661         case RENDERPATH_D3D10:
4662         case RENDERPATH_D3D11:
4663         case RENDERPATH_GLES2:
4664                 break;
4665         case RENDERPATH_GL13:
4666         case RENDERPATH_GL11:
4667                 wanttangents = false;
4668                 break;
4669         case RENDERPATH_SOFT:
4670                 break;
4671         }
4672
4673         if (r_shownormals.integer)
4674                 wanttangents = wantnormals = true;
4675
4676         // TODO: thread this
4677         // NOTE: R_PrepareRTLights() also caches entities
4678
4679         for (i = 0;i < r_refdef.scene.numentities;i++)
4680                 if (r_refdef.viewcache.entityvisible[i])
4681                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4682 }
4683
4684 //==================================================================================
4685
4686 static void R_View_UpdateEntityLighting (void)
4687 {
4688         int i;
4689         entity_render_t *ent;
4690         vec3_t tempdiffusenormal, avg;
4691         vec_t f, fa, fd, fdd;
4692         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4693
4694         for (i = 0;i < r_refdef.scene.numentities;i++)
4695         {
4696                 ent = r_refdef.scene.entities[i];
4697
4698                 // skip unseen models
4699                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4700                         continue;
4701
4702                 // skip bsp models
4703                 if (ent->model && ent->model->brush.num_leafs)
4704                 {
4705                         // TODO: use modellight for r_ambient settings on world?
4706                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4707                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4708                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4709                         continue;
4710                 }
4711
4712                 // fetch the lighting from the worldmodel data
4713                 VectorClear(ent->modellight_ambient);
4714                 VectorClear(ent->modellight_diffuse);
4715                 VectorClear(tempdiffusenormal);
4716                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4717                 {
4718                         vec3_t org;
4719                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4720
4721                         // complete lightning for lit sprites
4722                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4723                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4724                         {
4725                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4726                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4727                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4728                         }
4729                         else
4730                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4731
4732                         if(ent->flags & RENDER_EQUALIZE)
4733                         {
4734                                 // first fix up ambient lighting...
4735                                 if(r_equalize_entities_minambient.value > 0)
4736                                 {
4737                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4738                                         if(fd > 0)
4739                                         {
4740                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4741                                                 if(fa < r_equalize_entities_minambient.value * fd)
4742                                                 {
4743                                                         // solve:
4744                                                         //   fa'/fd' = minambient
4745                                                         //   fa'+0.25*fd' = fa+0.25*fd
4746                                                         //   ...
4747                                                         //   fa' = fd' * minambient
4748                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4749                                                         //   ...
4750                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4751                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4752                                                         //   ...
4753                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4754                                                         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
4755                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4756                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4757                                                 }
4758                                         }
4759                                 }
4760
4761                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4762                                 {
4763                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4764                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4765                                         f = fa + 0.25 * fd;
4766                                         if(f > 0)
4767                                         {
4768                                                 // adjust brightness and saturation to target
4769                                                 avg[0] = avg[1] = avg[2] = fa / f;
4770                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4771                                                 avg[0] = avg[1] = avg[2] = fd / f;
4772                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4773                                         }
4774                                 }
4775                         }
4776                 }
4777                 else // highly rare
4778                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4779
4780                 // move the light direction into modelspace coordinates for lighting code
4781                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4782                 if(VectorLength2(ent->modellight_lightdir) == 0)
4783                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4784                 VectorNormalize(ent->modellight_lightdir);
4785         }
4786 }
4787
4788 #define MAX_LINEOFSIGHTTRACES 64
4789
4790 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4791 {
4792         int i;
4793         vec3_t boxmins, boxmaxs;
4794         vec3_t start;
4795         vec3_t end;
4796         dp_model_t *model = r_refdef.scene.worldmodel;
4797
4798         if (!model || !model->brush.TraceLineOfSight)
4799                 return true;
4800
4801         // expand the box a little
4802         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4803         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4804         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4805         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4806         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4807         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4808
4809         // return true if eye is inside enlarged box
4810         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4811                 return true;
4812
4813         // try center
4814         VectorCopy(eye, start);
4815         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4816         if (model->brush.TraceLineOfSight(model, start, end))
4817                 return true;
4818
4819         // try various random positions
4820         for (i = 0;i < numsamples;i++)
4821         {
4822                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4823                 if (model->brush.TraceLineOfSight(model, start, end))
4824                         return true;
4825         }
4826
4827         return false;
4828 }
4829
4830
4831 static void R_View_UpdateEntityVisible (void)
4832 {
4833         int i;
4834         int renderimask;
4835         int samples;
4836         entity_render_t *ent;
4837
4838         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4839                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4840                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4841                 :                                                          RENDER_EXTERIORMODEL;
4842         if (!r_drawviewmodel.integer)
4843                 renderimask |= RENDER_VIEWMODEL;
4844         if (!r_drawexteriormodel.integer)
4845                 renderimask |= RENDER_EXTERIORMODEL;
4846         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4847         {
4848                 // worldmodel can check visibility
4849                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4850                 for (i = 0;i < r_refdef.scene.numentities;i++)
4851                 {
4852                         ent = r_refdef.scene.entities[i];
4853                         if (!(ent->flags & renderimask))
4854                         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)))
4855                         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))
4856                                 r_refdef.viewcache.entityvisible[i] = true;
4857                 }
4858                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4859                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4860                 {
4861                         for (i = 0;i < r_refdef.scene.numentities;i++)
4862                         {
4863                                 ent = r_refdef.scene.entities[i];
4864                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4865                                 {
4866                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4867                                         if (samples < 0)
4868                                                 continue; // temp entities do pvs only
4869                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4870                                                 ent->last_trace_visibility = realtime;
4871                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4872                                                 r_refdef.viewcache.entityvisible[i] = 0;
4873                                 }
4874                         }
4875                 }
4876         }
4877         else
4878         {
4879                 // no worldmodel or it can't check visibility
4880                 for (i = 0;i < r_refdef.scene.numentities;i++)
4881                 {
4882                         ent = r_refdef.scene.entities[i];
4883                         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));
4884                 }
4885         }
4886 }
4887
4888 /// only used if skyrendermasked, and normally returns false
4889 int R_DrawBrushModelsSky (void)
4890 {
4891         int i, sky;
4892         entity_render_t *ent;
4893
4894         sky = false;
4895         for (i = 0;i < r_refdef.scene.numentities;i++)
4896         {
4897                 if (!r_refdef.viewcache.entityvisible[i])
4898                         continue;
4899                 ent = r_refdef.scene.entities[i];
4900                 if (!ent->model || !ent->model->DrawSky)
4901                         continue;
4902                 ent->model->DrawSky(ent);
4903                 sky = true;
4904         }
4905         return sky;
4906 }
4907
4908 static void R_DrawNoModel(entity_render_t *ent);
4909 static void R_DrawModels(void)
4910 {
4911         int i;
4912         entity_render_t *ent;
4913
4914         for (i = 0;i < r_refdef.scene.numentities;i++)
4915         {
4916                 if (!r_refdef.viewcache.entityvisible[i])
4917                         continue;
4918                 ent = r_refdef.scene.entities[i];
4919                 r_refdef.stats.entities++;
4920                 if (ent->model && ent->model->Draw != NULL)
4921                         ent->model->Draw(ent);
4922                 else
4923                         R_DrawNoModel(ent);
4924         }
4925 }
4926
4927 static void R_DrawModelsDepth(void)
4928 {
4929         int i;
4930         entity_render_t *ent;
4931
4932         for (i = 0;i < r_refdef.scene.numentities;i++)
4933         {
4934                 if (!r_refdef.viewcache.entityvisible[i])
4935                         continue;
4936                 ent = r_refdef.scene.entities[i];
4937                 if (ent->model && ent->model->DrawDepth != NULL)
4938                         ent->model->DrawDepth(ent);
4939         }
4940 }
4941
4942 static void R_DrawModelsDebug(void)
4943 {
4944         int i;
4945         entity_render_t *ent;
4946
4947         for (i = 0;i < r_refdef.scene.numentities;i++)
4948         {
4949                 if (!r_refdef.viewcache.entityvisible[i])
4950                         continue;
4951                 ent = r_refdef.scene.entities[i];
4952                 if (ent->model && ent->model->DrawDebug != NULL)
4953                         ent->model->DrawDebug(ent);
4954         }
4955 }
4956
4957 static void R_DrawModelsAddWaterPlanes(void)
4958 {
4959         int i;
4960         entity_render_t *ent;
4961
4962         for (i = 0;i < r_refdef.scene.numentities;i++)
4963         {
4964                 if (!r_refdef.viewcache.entityvisible[i])
4965                         continue;
4966                 ent = r_refdef.scene.entities[i];
4967                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4968                         ent->model->DrawAddWaterPlanes(ent);
4969         }
4970 }
4971
4972 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4973 {
4974         if (r_hdr_irisadaptation.integer)
4975         {
4976                 vec3_t ambient;
4977                 vec3_t diffuse;
4978                 vec3_t diffusenormal;
4979                 vec_t brightness;
4980                 vec_t goal;
4981                 vec_t adjust;
4982                 vec_t current;
4983                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4984                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4985                 brightness = max(0.0000001f, brightness);
4986                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4987                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4988                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4989                 current = r_hdr_irisadaptation_value.value;
4990                 if (current < goal)
4991                         current = min(current + adjust, goal);
4992                 else if (current > goal)
4993                         current = max(current - adjust, goal);
4994                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4995                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4996         }
4997         else if (r_hdr_irisadaptation_value.value != 1.0f)
4998                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4999 }
5000
5001 static void R_View_SetFrustum(const int *scissor)
5002 {
5003         int i;
5004         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5005         vec3_t forward, left, up, origin, v;
5006
5007         if(scissor)
5008         {
5009                 // flipped x coordinates (because x points left here)
5010                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5011                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5012
5013                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5014                 switch(vid.renderpath)
5015                 {
5016                         case RENDERPATH_D3D9:
5017                         case RENDERPATH_D3D10:
5018                         case RENDERPATH_D3D11:
5019                         case RENDERPATH_SOFT:
5020                                 // non-flipped y coordinates
5021                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5022                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5023                                 break;
5024                         case RENDERPATH_GL11:
5025                         case RENDERPATH_GL13:
5026                         case RENDERPATH_GL20:
5027                         case RENDERPATH_GLES2:
5028                                 // non-flipped y coordinates
5029                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5030                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5031                                 break;
5032                 }
5033         }
5034
5035         // we can't trust r_refdef.view.forward and friends in reflected scenes
5036         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5037
5038 #if 0
5039         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5040         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5041         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5042         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5043         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5044         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5045         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5046         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5047         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5048         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5049         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5050         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5051 #endif
5052
5053 #if 0
5054         zNear = r_refdef.nearclip;
5055         nudge = 1.0 - 1.0 / (1<<23);
5056         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5057         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5058         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5059         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5060         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5061         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5062         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5063         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5064 #endif
5065
5066
5067
5068 #if 0
5069         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5070         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5071         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5072         r_refdef.view.frustum[0].dist = m[15] - m[12];
5073
5074         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5075         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5076         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5077         r_refdef.view.frustum[1].dist = m[15] + m[12];
5078
5079         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5080         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5081         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5082         r_refdef.view.frustum[2].dist = m[15] - m[13];
5083
5084         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5085         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5086         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5087         r_refdef.view.frustum[3].dist = m[15] + m[13];
5088
5089         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5090         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5091         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5092         r_refdef.view.frustum[4].dist = m[15] - m[14];
5093
5094         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5095         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5096         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5097         r_refdef.view.frustum[5].dist = m[15] + m[14];
5098 #endif
5099
5100         if (r_refdef.view.useperspective)
5101         {
5102                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5103                 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]);
5104                 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]);
5105                 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]);
5106                 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]);
5107
5108                 // then the normals from the corners relative to origin
5109                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5110                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5111                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5112                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5113
5114                 // in a NORMAL view, forward cross left == up
5115                 // in a REFLECTED view, forward cross left == down
5116                 // so our cross products above need to be adjusted for a left handed coordinate system
5117                 CrossProduct(forward, left, v);
5118                 if(DotProduct(v, up) < 0)
5119                 {
5120                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5121                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5122                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5123                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5124                 }
5125
5126                 // Leaving those out was a mistake, those were in the old code, and they
5127                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5128                 // I couldn't reproduce it after adding those normalizations. --blub
5129                 VectorNormalize(r_refdef.view.frustum[0].normal);
5130                 VectorNormalize(r_refdef.view.frustum[1].normal);
5131                 VectorNormalize(r_refdef.view.frustum[2].normal);
5132                 VectorNormalize(r_refdef.view.frustum[3].normal);
5133
5134                 // make the corners absolute
5135                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5136                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5137                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5138                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5139
5140                 // one more normal
5141                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5142
5143                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5144                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5145                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5146                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5147                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5148         }
5149         else
5150         {
5151                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5152                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5153                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5154                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5155                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5156                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5157                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5158                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5159                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5160                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5161         }
5162         r_refdef.view.numfrustumplanes = 5;
5163
5164         if (r_refdef.view.useclipplane)
5165         {
5166                 r_refdef.view.numfrustumplanes = 6;
5167                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5168         }
5169
5170         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5171                 PlaneClassify(r_refdef.view.frustum + i);
5172
5173         // LordHavoc: note to all quake engine coders, Quake had a special case
5174         // for 90 degrees which assumed a square view (wrong), so I removed it,
5175         // Quake2 has it disabled as well.
5176
5177         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5178         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5179         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5180         //PlaneClassify(&frustum[0]);
5181
5182         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5183         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5184         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5185         //PlaneClassify(&frustum[1]);
5186
5187         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5188         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5189         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5190         //PlaneClassify(&frustum[2]);
5191
5192         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5193         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5194         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5195         //PlaneClassify(&frustum[3]);
5196
5197         // nearclip plane
5198         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5199         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5200         //PlaneClassify(&frustum[4]);
5201 }
5202
5203 void R_View_UpdateWithScissor(const int *myscissor)
5204 {
5205         R_Main_ResizeViewCache();
5206         R_View_SetFrustum(myscissor);
5207         R_View_WorldVisibility(r_refdef.view.useclipplane);
5208         R_View_UpdateEntityVisible();
5209         R_View_UpdateEntityLighting();
5210 }
5211
5212 void R_View_Update(void)
5213 {
5214         R_Main_ResizeViewCache();
5215         R_View_SetFrustum(NULL);
5216         R_View_WorldVisibility(r_refdef.view.useclipplane);
5217         R_View_UpdateEntityVisible();
5218         R_View_UpdateEntityLighting();
5219 }
5220
5221 void R_SetupView(qboolean allowwaterclippingplane)
5222 {
5223         const float *customclipplane = NULL;
5224         float plane[4];
5225         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5226         {
5227                 // LordHavoc: couldn't figure out how to make this approach the
5228                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5229                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5230                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5231                         dist = r_refdef.view.clipplane.dist;
5232                 plane[0] = r_refdef.view.clipplane.normal[0];
5233                 plane[1] = r_refdef.view.clipplane.normal[1];
5234                 plane[2] = r_refdef.view.clipplane.normal[2];
5235                 plane[3] = dist;
5236                 customclipplane = plane;
5237         }
5238
5239         if (!r_refdef.view.useperspective)
5240                 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);
5241         else if (vid.stencil && r_useinfinitefarclip.integer)
5242                 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);
5243         else
5244                 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);
5245         R_SetViewport(&r_refdef.view.viewport);
5246 }
5247
5248 void R_EntityMatrix(const matrix4x4_t *matrix)
5249 {
5250         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5251         {
5252                 gl_modelmatrixchanged = false;
5253                 gl_modelmatrix = *matrix;
5254                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5255                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5256                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5257                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5258                 CHECKGLERROR
5259                 switch(vid.renderpath)
5260                 {
5261                 case RENDERPATH_D3D9:
5262 #ifdef SUPPORTD3D
5263                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5264                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5265 #endif
5266                         break;
5267                 case RENDERPATH_D3D10:
5268                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5269                         break;
5270                 case RENDERPATH_D3D11:
5271                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5272                         break;
5273                 case RENDERPATH_GL13:
5274                 case RENDERPATH_GL11:
5275                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5276                         break;
5277                 case RENDERPATH_SOFT:
5278                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5279                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5280                         break;
5281                 case RENDERPATH_GL20:
5282                 case RENDERPATH_GLES2:
5283                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5284                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5285                         break;
5286                 }
5287         }
5288 }
5289
5290 void R_ResetViewRendering2D(void)
5291 {
5292         r_viewport_t viewport;
5293         DrawQ_Finish();
5294
5295         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5296         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);
5297         R_SetViewport(&viewport);
5298         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5299         GL_Color(1, 1, 1, 1);
5300         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5301         GL_BlendFunc(GL_ONE, GL_ZERO);
5302         GL_ScissorTest(false);
5303         GL_DepthMask(false);
5304         GL_DepthRange(0, 1);
5305         GL_DepthTest(false);
5306         GL_DepthFunc(GL_LEQUAL);
5307         R_EntityMatrix(&identitymatrix);
5308         R_Mesh_ResetTextureState();
5309         GL_PolygonOffset(0, 0);
5310         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5311         switch(vid.renderpath)
5312         {
5313         case RENDERPATH_GL11:
5314         case RENDERPATH_GL13:
5315         case RENDERPATH_GL20:
5316         case RENDERPATH_GLES2:
5317                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5318                 break;
5319         case RENDERPATH_D3D9:
5320         case RENDERPATH_D3D10:
5321         case RENDERPATH_D3D11:
5322         case RENDERPATH_SOFT:
5323                 break;
5324         }
5325         GL_CullFace(GL_NONE);
5326 }
5327
5328 void R_ResetViewRendering3D(void)
5329 {
5330         DrawQ_Finish();
5331
5332         R_SetupView(true);
5333         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5334         GL_Color(1, 1, 1, 1);
5335         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5336         GL_BlendFunc(GL_ONE, GL_ZERO);
5337         GL_ScissorTest(true);
5338         GL_DepthMask(true);
5339         GL_DepthRange(0, 1);
5340         GL_DepthTest(true);
5341         GL_DepthFunc(GL_LEQUAL);
5342         R_EntityMatrix(&identitymatrix);
5343         R_Mesh_ResetTextureState();
5344         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5345         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5346         switch(vid.renderpath)
5347         {
5348         case RENDERPATH_GL11:
5349         case RENDERPATH_GL13:
5350         case RENDERPATH_GL20:
5351         case RENDERPATH_GLES2:
5352                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5353                 break;
5354         case RENDERPATH_D3D9:
5355         case RENDERPATH_D3D10:
5356         case RENDERPATH_D3D11:
5357         case RENDERPATH_SOFT:
5358                 break;
5359         }
5360         GL_CullFace(r_refdef.view.cullface_back);
5361 }
5362
5363 /*
5364 ================
5365 R_RenderView_UpdateViewVectors
5366 ================
5367 */
5368 static void R_RenderView_UpdateViewVectors(void)
5369 {
5370         // break apart the view matrix into vectors for various purposes
5371         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5372         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5373         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5374         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5375         // make an inverted copy of the view matrix for tracking sprites
5376         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5377 }
5378
5379 void R_RenderScene(void);
5380 void R_RenderWaterPlanes(void);
5381
5382 static void R_Water_StartFrame(void)
5383 {
5384         int i;
5385         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5386         r_waterstate_waterplane_t *p;
5387
5388         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5389                 return;
5390
5391         switch(vid.renderpath)
5392         {
5393         case RENDERPATH_GL20:
5394         case RENDERPATH_D3D9:
5395         case RENDERPATH_D3D10:
5396         case RENDERPATH_D3D11:
5397         case RENDERPATH_SOFT:
5398         case RENDERPATH_GLES2:
5399                 break;
5400         case RENDERPATH_GL13:
5401         case RENDERPATH_GL11:
5402                 return;
5403         }
5404
5405         // set waterwidth and waterheight to the water resolution that will be
5406         // used (often less than the screen resolution for faster rendering)
5407         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5408         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5409
5410         // calculate desired texture sizes
5411         // can't use water if the card does not support the texture size
5412         if (!r_water.integer || r_showsurfaces.integer)
5413                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5414         else if (vid.support.arb_texture_non_power_of_two)
5415         {
5416                 texturewidth = waterwidth;
5417                 textureheight = waterheight;
5418                 camerawidth = waterwidth;
5419                 cameraheight = waterheight;
5420         }
5421         else
5422         {
5423                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5424                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5425                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5426                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5427         }
5428
5429         // allocate textures as needed
5430         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5431         {
5432                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5433                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5434                 {
5435                         if (p->texture_refraction)
5436                                 R_FreeTexture(p->texture_refraction);
5437                         p->texture_refraction = NULL;
5438                         if (p->texture_reflection)
5439                                 R_FreeTexture(p->texture_reflection);
5440                         p->texture_reflection = NULL;
5441                         if (p->texture_camera)
5442                                 R_FreeTexture(p->texture_camera);
5443                         p->texture_camera = NULL;
5444                 }
5445                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5446                 r_waterstate.texturewidth = texturewidth;
5447                 r_waterstate.textureheight = textureheight;
5448                 r_waterstate.camerawidth = camerawidth;
5449                 r_waterstate.cameraheight = cameraheight;
5450         }
5451
5452         if (r_waterstate.texturewidth)
5453         {
5454                 r_waterstate.enabled = true;
5455
5456                 // when doing a reduced render (HDR) we want to use a smaller area
5457                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5458                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5459
5460                 // set up variables that will be used in shader setup
5461                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5462                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5463                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5464                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5465         }
5466
5467         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5468         r_waterstate.numwaterplanes = 0;
5469 }
5470
5471 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5472 {
5473         int triangleindex, planeindex;
5474         const int *e;
5475         vec3_t vert[3];
5476         vec3_t normal;
5477         vec3_t center;
5478         mplane_t plane;
5479         r_waterstate_waterplane_t *p;
5480         texture_t *t = R_GetCurrentTexture(surface->texture);
5481
5482         // just use the first triangle with a valid normal for any decisions
5483         VectorClear(normal);
5484         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5485         {
5486                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5487                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5488                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5489                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5490                 if (VectorLength2(normal) >= 0.001)
5491                         break;
5492         }
5493
5494         VectorCopy(normal, plane.normal);
5495         VectorNormalize(plane.normal);
5496         plane.dist = DotProduct(vert[0], plane.normal);
5497         PlaneClassify(&plane);
5498         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5499         {
5500                 // skip backfaces (except if nocullface is set)
5501                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5502                         return;
5503                 VectorNegate(plane.normal, plane.normal);
5504                 plane.dist *= -1;
5505                 PlaneClassify(&plane);
5506         }
5507
5508
5509         // find a matching plane if there is one
5510         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5511                 if(p->camera_entity == t->camera_entity)
5512                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5513                                 break;
5514         if (planeindex >= r_waterstate.maxwaterplanes)
5515                 return; // nothing we can do, out of planes
5516
5517         // if this triangle does not fit any known plane rendered this frame, add one
5518         if (planeindex >= r_waterstate.numwaterplanes)
5519         {
5520                 // store the new plane
5521                 r_waterstate.numwaterplanes++;
5522                 p->plane = plane;
5523                 // clear materialflags and pvs
5524                 p->materialflags = 0;
5525                 p->pvsvalid = false;
5526                 p->camera_entity = t->camera_entity;
5527                 VectorCopy(surface->mins, p->mins);
5528                 VectorCopy(surface->maxs, p->maxs);
5529         }
5530         else
5531         {
5532                 // merge mins/maxs
5533                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5534                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5535                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5536                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5537                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5538                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5539         }
5540         // merge this surface's materialflags into the waterplane
5541         p->materialflags |= t->currentmaterialflags;
5542         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5543         {
5544                 // merge this surface's PVS into the waterplane
5545                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5546                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5547                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5548                 {
5549                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5550                         p->pvsvalid = true;
5551                 }
5552         }
5553 }
5554
5555 static void R_Water_ProcessPlanes(void)
5556 {
5557         int myscissor[4];
5558         r_refdef_view_t originalview;
5559         r_refdef_view_t myview;
5560         int planeindex;
5561         r_waterstate_waterplane_t *p;
5562         vec3_t visorigin;
5563
5564         originalview = r_refdef.view;
5565
5566         // make sure enough textures are allocated
5567         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5568         {
5569                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5570                 {
5571                         if (!p->texture_refraction)
5572                                 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);
5573                         if (!p->texture_refraction)
5574                                 goto error;
5575                 }
5576                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5577                 {
5578                         if (!p->texture_camera)
5579                                 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);
5580                         if (!p->texture_camera)
5581                                 goto error;
5582                 }
5583
5584                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5585                 {
5586                         if (!p->texture_reflection)
5587                                 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);
5588                         if (!p->texture_reflection)
5589                                 goto error;
5590                 }
5591         }
5592
5593         // render views
5594         r_refdef.view = originalview;
5595         r_refdef.view.showdebug = false;
5596         r_refdef.view.width = r_waterstate.waterwidth;
5597         r_refdef.view.height = r_waterstate.waterheight;
5598         r_refdef.view.useclipplane = true;
5599         myview = r_refdef.view;
5600         r_waterstate.renderingscene = true;
5601         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5602         {
5603                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5604                 {
5605                         r_refdef.view = myview;
5606                         if(r_water_scissormode.integer)
5607                         {
5608                                 R_SetupView(true);
5609                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5610                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5611                         }
5612
5613                         // render reflected scene and copy into texture
5614                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5615                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5616                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5617                         r_refdef.view.clipplane = p->plane;
5618
5619                         // reverse the cullface settings for this render
5620                         r_refdef.view.cullface_front = GL_FRONT;
5621                         r_refdef.view.cullface_back = GL_BACK;
5622                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5623                         {
5624                                 r_refdef.view.usecustompvs = true;
5625                                 if (p->pvsvalid)
5626                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5627                                 else
5628                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5629                         }
5630
5631                         R_ResetViewRendering3D();
5632                         R_ClearScreen(r_refdef.fogenabled);
5633                         if(r_water_scissormode.integer & 2)
5634                                 R_View_UpdateWithScissor(myscissor);
5635                         else
5636                                 R_View_Update();
5637                         if(r_water_scissormode.integer & 1)
5638                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5639                         R_RenderScene();
5640
5641                         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);
5642                 }
5643
5644                 // render the normal view scene and copy into texture
5645                 // (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)
5646                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5647                 {
5648                         r_refdef.view = myview;
5649                         if(r_water_scissormode.integer)
5650                         {
5651                                 R_SetupView(true);
5652                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5653                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5654                         }
5655
5656                         r_waterstate.renderingrefraction = true;
5657
5658                         r_refdef.view.clipplane = p->plane;
5659                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5660                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5661
5662                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5663                         {
5664                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5665                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5666                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5667                                 R_RenderView_UpdateViewVectors();
5668                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5669                                 {
5670                                         r_refdef.view.usecustompvs = true;
5671                                         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);
5672                                 }
5673                         }
5674
5675                         PlaneClassify(&r_refdef.view.clipplane);
5676
5677                         R_ResetViewRendering3D();
5678                         R_ClearScreen(r_refdef.fogenabled);
5679                         if(r_water_scissormode.integer & 2)
5680                                 R_View_UpdateWithScissor(myscissor);
5681                         else
5682                                 R_View_Update();
5683                         if(r_water_scissormode.integer & 1)
5684                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5685                         R_RenderScene();
5686
5687                         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);
5688                         r_waterstate.renderingrefraction = false;
5689                 }
5690                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5691                 {
5692                         r_refdef.view = myview;
5693
5694                         r_refdef.view.clipplane = p->plane;
5695                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5696                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5697
5698                         r_refdef.view.width = r_waterstate.camerawidth;
5699                         r_refdef.view.height = r_waterstate.cameraheight;
5700                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5701                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5702
5703                         if(p->camera_entity)
5704                         {
5705                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5706                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5707                         }
5708
5709                         // note: all of the view is used for displaying... so
5710                         // there is no use in scissoring
5711
5712                         // reverse the cullface settings for this render
5713                         r_refdef.view.cullface_front = GL_FRONT;
5714                         r_refdef.view.cullface_back = GL_BACK;
5715                         // also reverse the view matrix
5716                         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
5717                         R_RenderView_UpdateViewVectors();
5718                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5719                         {
5720                                 r_refdef.view.usecustompvs = true;
5721                                 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);
5722                         }
5723                         
5724                         // camera needs no clipplane
5725                         r_refdef.view.useclipplane = false;
5726
5727                         PlaneClassify(&r_refdef.view.clipplane);
5728
5729                         R_ResetViewRendering3D();
5730                         R_ClearScreen(r_refdef.fogenabled);
5731                         R_View_Update();
5732                         R_RenderScene();
5733
5734                         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);
5735                         r_waterstate.renderingrefraction = false;
5736                 }
5737
5738         }
5739         r_waterstate.renderingscene = false;
5740         r_refdef.view = originalview;
5741         R_ResetViewRendering3D();
5742         R_ClearScreen(r_refdef.fogenabled);
5743         R_View_Update();
5744         return;
5745 error:
5746         r_refdef.view = originalview;
5747         r_waterstate.renderingscene = false;
5748         Cvar_SetValueQuick(&r_water, 0);
5749         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5750         return;
5751 }
5752
5753 void R_Bloom_StartFrame(void)
5754 {
5755         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5756
5757         switch(vid.renderpath)
5758         {
5759         case RENDERPATH_GL20:
5760         case RENDERPATH_D3D9:
5761         case RENDERPATH_D3D10:
5762         case RENDERPATH_D3D11:
5763         case RENDERPATH_SOFT:
5764         case RENDERPATH_GLES2:
5765                 break;
5766         case RENDERPATH_GL13:
5767         case RENDERPATH_GL11:
5768                 return;
5769         }
5770
5771         // set bloomwidth and bloomheight to the bloom resolution that will be
5772         // used (often less than the screen resolution for faster rendering)
5773         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5774         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5775         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5776         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5777         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5778
5779         // calculate desired texture sizes
5780         if (vid.support.arb_texture_non_power_of_two)
5781         {
5782                 screentexturewidth = r_refdef.view.width;
5783                 screentextureheight = r_refdef.view.height;
5784                 bloomtexturewidth = r_bloomstate.bloomwidth;
5785                 bloomtextureheight = r_bloomstate.bloomheight;
5786         }
5787         else
5788         {
5789                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5790                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5791                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5792                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5793         }
5794
5795         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))
5796         {
5797                 Cvar_SetValueQuick(&r_hdr, 0);
5798                 Cvar_SetValueQuick(&r_bloom, 0);
5799                 Cvar_SetValueQuick(&r_motionblur, 0);
5800                 Cvar_SetValueQuick(&r_damageblur, 0);
5801         }
5802
5803         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)))
5804                 screentexturewidth = screentextureheight = 0;
5805         if (!r_hdr.integer && !r_bloom.integer)
5806                 bloomtexturewidth = bloomtextureheight = 0;
5807
5808         // allocate textures as needed
5809         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5810         {
5811                 if (r_bloomstate.texture_screen)
5812                         R_FreeTexture(r_bloomstate.texture_screen);
5813                 r_bloomstate.texture_screen = NULL;
5814                 r_bloomstate.screentexturewidth = screentexturewidth;
5815                 r_bloomstate.screentextureheight = screentextureheight;
5816                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5817                         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);
5818         }
5819         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5820         {
5821                 if (r_bloomstate.texture_bloom)
5822                         R_FreeTexture(r_bloomstate.texture_bloom);
5823                 r_bloomstate.texture_bloom = NULL;
5824                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5825                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5826                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5827                         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);
5828         }
5829
5830         // when doing a reduced render (HDR) we want to use a smaller area
5831         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5832         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5833         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5834         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5835         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5836
5837         // set up a texcoord array for the full resolution screen image
5838         // (we have to keep this around to copy back during final render)
5839         r_bloomstate.screentexcoord2f[0] = 0;
5840         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5841         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5842         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5843         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5844         r_bloomstate.screentexcoord2f[5] = 0;
5845         r_bloomstate.screentexcoord2f[6] = 0;
5846         r_bloomstate.screentexcoord2f[7] = 0;
5847
5848         // set up a texcoord array for the reduced resolution bloom image
5849         // (which will be additive blended over the screen image)
5850         r_bloomstate.bloomtexcoord2f[0] = 0;
5851         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5852         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5853         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5854         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5855         r_bloomstate.bloomtexcoord2f[5] = 0;
5856         r_bloomstate.bloomtexcoord2f[6] = 0;
5857         r_bloomstate.bloomtexcoord2f[7] = 0;
5858
5859         switch(vid.renderpath)
5860         {
5861         case RENDERPATH_GL11:
5862         case RENDERPATH_GL13:
5863         case RENDERPATH_GL20:
5864         case RENDERPATH_SOFT:
5865         case RENDERPATH_GLES2:
5866                 break;
5867         case RENDERPATH_D3D9:
5868         case RENDERPATH_D3D10:
5869         case RENDERPATH_D3D11:
5870                 {
5871                         int i;
5872                         for (i = 0;i < 4;i++)
5873                         {
5874                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5875                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5876                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5877                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5878                         }
5879                 }
5880                 break;
5881         }
5882
5883         if (r_hdr.integer || r_bloom.integer)
5884         {
5885                 r_bloomstate.enabled = true;
5886                 r_bloomstate.hdr = r_hdr.integer != 0;
5887         }
5888
5889         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);
5890 }
5891
5892 void R_Bloom_CopyBloomTexture(float colorscale)
5893 {
5894         r_refdef.stats.bloom++;
5895
5896         // scale down screen texture to the bloom texture size
5897         CHECKGLERROR
5898         R_SetViewport(&r_bloomstate.viewport);
5899         GL_BlendFunc(GL_ONE, GL_ZERO);
5900         GL_Color(colorscale, colorscale, colorscale, 1);
5901         // 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...
5902         switch(vid.renderpath)
5903         {
5904         case RENDERPATH_GL11:
5905         case RENDERPATH_GL13:
5906         case RENDERPATH_GL20:
5907         case RENDERPATH_SOFT:
5908         case RENDERPATH_GLES2:
5909                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5910                 break;
5911         case RENDERPATH_D3D9:
5912         case RENDERPATH_D3D10:
5913         case RENDERPATH_D3D11:
5914                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5915                 break;
5916         }
5917         // TODO: do boxfilter scale-down in shader?
5918         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5919         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5920         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5921
5922         // we now have a bloom image in the framebuffer
5923         // copy it into the bloom image texture for later processing
5924         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);
5925         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5926 }
5927
5928 void R_Bloom_CopyHDRTexture(void)
5929 {
5930         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);
5931         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5932 }
5933
5934 void R_Bloom_MakeTexture(void)
5935 {
5936         int x, range, dir;
5937         float xoffset, yoffset, r, brighten;
5938
5939         r_refdef.stats.bloom++;
5940
5941         R_ResetViewRendering2D();
5942
5943         // we have a bloom image in the framebuffer
5944         CHECKGLERROR
5945         R_SetViewport(&r_bloomstate.viewport);
5946
5947         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5948         {
5949                 x *= 2;
5950                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5951                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5952                 GL_Color(r,r,r,1);
5953                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5954                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5955                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5956                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5957
5958                 // copy the vertically blurred bloom view to a texture
5959                 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);
5960                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5961         }
5962
5963         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5964         brighten = r_bloom_brighten.value;
5965         if (r_hdr.integer)
5966                 brighten *= r_hdr_range.value;
5967         brighten = sqrt(brighten);
5968         if(range >= 1)
5969                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5970         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5971
5972         for (dir = 0;dir < 2;dir++)
5973         {
5974                 // blend on at multiple vertical offsets to achieve a vertical blur
5975                 // TODO: do offset blends using GLSL
5976                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5977                 GL_BlendFunc(GL_ONE, GL_ZERO);
5978                 for (x = -range;x <= range;x++)
5979                 {
5980                         if (!dir){xoffset = 0;yoffset = x;}
5981                         else {xoffset = x;yoffset = 0;}
5982                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5983                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5984                         // compute a texcoord array with the specified x and y offset
5985                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5986                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5987                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5988                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5989                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5990                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5991                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5992                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5993                         // this r value looks like a 'dot' particle, fading sharply to
5994                         // black at the edges
5995                         // (probably not realistic but looks good enough)
5996                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5997                         //r = brighten/(range*2+1);
5998                         r = brighten / (range * 2 + 1);
5999                         if(range >= 1)
6000                                 r *= (1 - x*x/(float)(range*range));
6001                         GL_Color(r, r, r, 1);
6002                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6003                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6004                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6005                         GL_BlendFunc(GL_ONE, GL_ONE);
6006                 }
6007
6008                 // copy the vertically blurred bloom view to a texture
6009                 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);
6010                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6011         }
6012 }
6013
6014 void R_HDR_RenderBloomTexture(void)
6015 {
6016         int oldwidth, oldheight;
6017         float oldcolorscale;
6018         qboolean oldwaterstate;
6019
6020         oldwaterstate = r_waterstate.enabled;
6021         oldcolorscale = r_refdef.view.colorscale;
6022         oldwidth = r_refdef.view.width;
6023         oldheight = r_refdef.view.height;
6024         r_refdef.view.width = r_bloomstate.bloomwidth;
6025         r_refdef.view.height = r_bloomstate.bloomheight;
6026
6027         if(r_hdr.integer < 2)
6028                 r_waterstate.enabled = false;
6029
6030         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6031         // TODO: add exposure compensation features
6032         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6033
6034         r_refdef.view.showdebug = false;
6035         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6036
6037         R_ResetViewRendering3D();
6038
6039         R_ClearScreen(r_refdef.fogenabled);
6040         if (r_timereport_active)
6041                 R_TimeReport("HDRclear");
6042
6043         R_View_Update();
6044         if (r_timereport_active)
6045                 R_TimeReport("visibility");
6046
6047         // only do secondary renders with HDR if r_hdr is 2 or higher
6048         r_waterstate.numwaterplanes = 0;
6049         if (r_waterstate.enabled)
6050                 R_RenderWaterPlanes();
6051
6052         r_refdef.view.showdebug = true;
6053         R_RenderScene();
6054         r_waterstate.numwaterplanes = 0;
6055
6056         R_ResetViewRendering2D();
6057
6058         R_Bloom_CopyHDRTexture();
6059         R_Bloom_MakeTexture();
6060
6061         // restore the view settings
6062         r_waterstate.enabled = oldwaterstate;
6063         r_refdef.view.width = oldwidth;
6064         r_refdef.view.height = oldheight;
6065         r_refdef.view.colorscale = oldcolorscale;
6066
6067         R_ResetViewRendering3D();
6068
6069         R_ClearScreen(r_refdef.fogenabled);
6070         if (r_timereport_active)
6071                 R_TimeReport("viewclear");
6072 }
6073
6074 static void R_BlendView(void)
6075 {
6076         unsigned int permutation;
6077         float uservecs[4][4];
6078
6079         switch (vid.renderpath)
6080         {
6081         case RENDERPATH_GL20:
6082         case RENDERPATH_D3D9:
6083         case RENDERPATH_D3D10:
6084         case RENDERPATH_D3D11:
6085         case RENDERPATH_SOFT:
6086         case RENDERPATH_GLES2:
6087                 permutation =
6088                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6089                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6090                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6091                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6092                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6093
6094                 if (r_bloomstate.texture_screen)
6095                 {
6096                         // make sure the buffer is available
6097                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6098
6099                         R_ResetViewRendering2D();
6100
6101                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6102                         {
6103                                 // declare variables
6104                                 float speed;
6105                                 static float avgspeed;
6106
6107                                 speed = VectorLength(cl.movement_velocity);
6108
6109                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6110                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6111
6112                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6113                                 speed = bound(0, speed, 1);
6114                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6115
6116                                 // calculate values into a standard alpha
6117                                 cl.motionbluralpha = 1 - exp(-
6118                                                 (
6119                                                  (r_motionblur.value * speed / 80)
6120                                                  +
6121                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6122                                                 )
6123                                                 /
6124                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6125                                            );
6126
6127                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6128                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6129                                 // apply the blur
6130                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6131                                 {
6132                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6133                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6134                                         switch(vid.renderpath)
6135                                         {
6136                                         case RENDERPATH_GL11:
6137                                         case RENDERPATH_GL13:
6138                                         case RENDERPATH_GL20:
6139                                         case RENDERPATH_SOFT:
6140                                         case RENDERPATH_GLES2:
6141                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6142                                                 break;
6143                                         case RENDERPATH_D3D9:
6144                                         case RENDERPATH_D3D10:
6145                                         case RENDERPATH_D3D11:
6146                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6147                                                 break;
6148                                         }
6149                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6150                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6151                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6152                                 }
6153                         }
6154
6155                         // copy view into the screen texture
6156                         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);
6157                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6158                 }
6159                 else if (!r_bloomstate.texture_bloom)
6160                 {
6161                         // we may still have to do view tint...
6162                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6163                         {
6164                                 // apply a color tint to the whole view
6165                                 R_ResetViewRendering2D();
6166                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6167                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6168                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6169                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6170                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6171                         }
6172                         break; // no screen processing, no bloom, skip it
6173                 }
6174
6175                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6176                 {
6177                         // render simple bloom effect
6178                         // copy the screen and shrink it and darken it for the bloom process
6179                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6180                         // make the bloom texture
6181                         R_Bloom_MakeTexture();
6182                 }
6183
6184 #if _MSC_VER >= 1400
6185 #define sscanf sscanf_s
6186 #endif
6187                 memset(uservecs, 0, sizeof(uservecs));
6188                 if (r_glsl_postprocess_uservec1_enable.integer)
6189                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6190                 if (r_glsl_postprocess_uservec2_enable.integer)
6191                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6192                 if (r_glsl_postprocess_uservec3_enable.integer)
6193                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6194                 if (r_glsl_postprocess_uservec4_enable.integer)
6195                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6196
6197                 R_ResetViewRendering2D();
6198                 GL_Color(1, 1, 1, 1);
6199                 GL_BlendFunc(GL_ONE, GL_ZERO);
6200
6201                 switch(vid.renderpath)
6202                 {
6203                 case RENDERPATH_GL20:
6204                 case RENDERPATH_GLES2:
6205                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6206                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6207                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6208                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6209                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6210                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6211                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6212                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6213                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6214                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6215                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6216                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6217                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6218                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6219                         break;
6220                 case RENDERPATH_D3D9:
6221 #ifdef SUPPORTD3D
6222                         // 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...
6223                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6224                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6225                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6226                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6227                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6228                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6229                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6230                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6231                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6232                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6233                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6234                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6235                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6236                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6237 #endif
6238                         break;
6239                 case RENDERPATH_D3D10:
6240                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6241                         break;
6242                 case RENDERPATH_D3D11:
6243                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6244                         break;
6245                 case RENDERPATH_SOFT:
6246                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6247                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6248                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6249                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6250                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6251                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6252                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6253                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6254                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6255                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6256                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6257                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6258                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6259                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6260                         break;
6261                 default:
6262                         break;
6263                 }
6264                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6265                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6266                 break;
6267         case RENDERPATH_GL13:
6268         case RENDERPATH_GL11:
6269                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6270                 {
6271                         // apply a color tint to the whole view
6272                         R_ResetViewRendering2D();
6273                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6274                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6275                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6276                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6277                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278                 }
6279                 break;
6280         }
6281 }
6282
6283 matrix4x4_t r_waterscrollmatrix;
6284
6285 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6286 {
6287         if (r_refdef.fog_density)
6288         {
6289                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6290                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6291                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6292
6293                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6294                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6295                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6296                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6297
6298                 {
6299                         vec3_t fogvec;
6300                         VectorCopy(r_refdef.fogcolor, fogvec);
6301                         //   color.rgb *= ContrastBoost * SceneBrightness;
6302                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6303                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6304                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6305                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6306                 }
6307         }
6308 }
6309
6310 void R_UpdateVariables(void)
6311 {
6312         R_Textures_Frame();
6313
6314         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6315
6316         r_refdef.farclip = r_farclip_base.value;
6317         if (r_refdef.scene.worldmodel)
6318                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6319         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6320
6321         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6322                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6323         r_refdef.polygonfactor = 0;
6324         r_refdef.polygonoffset = 0;
6325         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6326         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6327
6328         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6329         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6330         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6331         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6332         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6333         if (FAKELIGHT_ENABLED)
6334         {
6335                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6336         }
6337         if (r_showsurfaces.integer)
6338         {
6339                 r_refdef.scene.rtworld = false;
6340                 r_refdef.scene.rtworldshadows = false;
6341                 r_refdef.scene.rtdlight = false;
6342                 r_refdef.scene.rtdlightshadows = false;
6343                 r_refdef.lightmapintensity = 0;
6344         }
6345
6346         if (gamemode == GAME_NEHAHRA)
6347         {
6348                 if (gl_fogenable.integer)
6349                 {
6350                         r_refdef.oldgl_fogenable = true;
6351                         r_refdef.fog_density = gl_fogdensity.value;
6352                         r_refdef.fog_red = gl_fogred.value;
6353                         r_refdef.fog_green = gl_foggreen.value;
6354                         r_refdef.fog_blue = gl_fogblue.value;
6355                         r_refdef.fog_alpha = 1;
6356                         r_refdef.fog_start = 0;
6357                         r_refdef.fog_end = gl_skyclip.value;
6358                         r_refdef.fog_height = 1<<30;
6359                         r_refdef.fog_fadedepth = 128;
6360                 }
6361                 else if (r_refdef.oldgl_fogenable)
6362                 {
6363                         r_refdef.oldgl_fogenable = false;
6364                         r_refdef.fog_density = 0;
6365                         r_refdef.fog_red = 0;
6366                         r_refdef.fog_green = 0;
6367                         r_refdef.fog_blue = 0;
6368                         r_refdef.fog_alpha = 0;
6369                         r_refdef.fog_start = 0;
6370                         r_refdef.fog_end = 0;
6371                         r_refdef.fog_height = 1<<30;
6372                         r_refdef.fog_fadedepth = 128;
6373                 }
6374         }
6375
6376         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6377         r_refdef.fog_start = max(0, r_refdef.fog_start);
6378         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6379
6380         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6381
6382         if (r_refdef.fog_density && r_drawfog.integer)
6383         {
6384                 r_refdef.fogenabled = true;
6385                 // this is the point where the fog reaches 0.9986 alpha, which we
6386                 // consider a good enough cutoff point for the texture
6387                 // (0.9986 * 256 == 255.6)
6388                 if (r_fog_exp2.integer)
6389                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6390                 else
6391                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6392                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6393                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6394                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6395                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6396                         R_BuildFogHeightTexture();
6397                 // fog color was already set
6398                 // update the fog texture
6399                 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)
6400                         R_BuildFogTexture();
6401                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6402                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6403         }
6404         else
6405                 r_refdef.fogenabled = false;
6406
6407         switch(vid.renderpath)
6408         {
6409         case RENDERPATH_GL20:
6410         case RENDERPATH_D3D9:
6411         case RENDERPATH_D3D10:
6412         case RENDERPATH_D3D11:
6413         case RENDERPATH_SOFT:
6414         case RENDERPATH_GLES2:
6415                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6416                 {
6417                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6418                         {
6419                                 // build GLSL gamma texture
6420 #define RAMPWIDTH 256
6421                                 unsigned short ramp[RAMPWIDTH * 3];
6422                                 unsigned char rampbgr[RAMPWIDTH][4];
6423                                 int i;
6424
6425                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6426
6427                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6428                                 for(i = 0; i < RAMPWIDTH; ++i)
6429                                 {
6430                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6431                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6432                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6433                                         rampbgr[i][3] = 0;
6434                                 }
6435                                 if (r_texture_gammaramps)
6436                                 {
6437                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6438                                 }
6439                                 else
6440                                 {
6441                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6442                                 }
6443                         }
6444                 }
6445                 else
6446                 {
6447                         // remove GLSL gamma texture
6448                 }
6449                 break;
6450         case RENDERPATH_GL13:
6451         case RENDERPATH_GL11:
6452                 break;
6453         }
6454 }
6455
6456 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6457 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6458 /*
6459 ================
6460 R_SelectScene
6461 ================
6462 */
6463 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6464         if( scenetype != r_currentscenetype ) {
6465                 // store the old scenetype
6466                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6467                 r_currentscenetype = scenetype;
6468                 // move in the new scene
6469                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6470         }
6471 }
6472
6473 /*
6474 ================
6475 R_GetScenePointer
6476 ================
6477 */
6478 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6479 {
6480         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6481         if( scenetype == r_currentscenetype ) {
6482                 return &r_refdef.scene;
6483         } else {
6484                 return &r_scenes_store[ scenetype ];
6485         }
6486 }
6487
6488 /*
6489 ================
6490 R_RenderView
6491 ================
6492 */
6493 int dpsoftrast_test;
6494 void R_RenderView(void)
6495 {
6496         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6497
6498         dpsoftrast_test = r_test.integer;
6499
6500         if (r_timereport_active)
6501                 R_TimeReport("start");
6502         r_textureframe++; // used only by R_GetCurrentTexture
6503         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6504
6505         if(R_CompileShader_CheckStaticParms())
6506                 R_GLSL_Restart_f();
6507
6508         if (!r_drawentities.integer)
6509                 r_refdef.scene.numentities = 0;
6510
6511         R_AnimCache_ClearCache();
6512         R_FrameData_NewFrame();
6513
6514         /* adjust for stereo display */
6515         if(R_Stereo_Active())
6516         {
6517                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
6518                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6519         }
6520
6521         if (r_refdef.view.isoverlay)
6522         {
6523                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6524                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6525                 R_TimeReport("depthclear");
6526
6527                 r_refdef.view.showdebug = false;
6528
6529                 r_waterstate.enabled = false;
6530                 r_waterstate.numwaterplanes = 0;
6531
6532                 R_RenderScene();
6533
6534                 r_refdef.view.matrix = originalmatrix;
6535
6536                 CHECKGLERROR
6537                 return;
6538         }
6539
6540         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6541         {
6542                 r_refdef.view.matrix = originalmatrix;
6543                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6544         }
6545
6546         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6547
6548         R_RenderView_UpdateViewVectors();
6549
6550         R_Shadow_UpdateWorldLightSelection();
6551
6552         R_Bloom_StartFrame();
6553         R_Water_StartFrame();
6554
6555         CHECKGLERROR
6556         if (r_timereport_active)
6557                 R_TimeReport("viewsetup");
6558
6559         R_ResetViewRendering3D();
6560
6561         if (r_refdef.view.clear || r_refdef.fogenabled)
6562         {
6563                 R_ClearScreen(r_refdef.fogenabled);
6564                 if (r_timereport_active)
6565                         R_TimeReport("viewclear");
6566         }
6567         r_refdef.view.clear = true;
6568
6569         // this produces a bloom texture to be used in R_BlendView() later
6570         if (r_hdr.integer && r_bloomstate.bloomwidth)
6571         {
6572                 R_HDR_RenderBloomTexture();
6573                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6574                 r_textureframe++; // used only by R_GetCurrentTexture
6575         }
6576
6577         r_refdef.view.showdebug = true;
6578
6579         R_View_Update();
6580         if (r_timereport_active)
6581                 R_TimeReport("visibility");
6582
6583         r_waterstate.numwaterplanes = 0;
6584         if (r_waterstate.enabled)
6585                 R_RenderWaterPlanes();
6586
6587         R_RenderScene();
6588         r_waterstate.numwaterplanes = 0;
6589
6590         R_BlendView();
6591         if (r_timereport_active)
6592                 R_TimeReport("blendview");
6593
6594         GL_Scissor(0, 0, vid.width, vid.height);
6595         GL_ScissorTest(false);
6596
6597         r_refdef.view.matrix = originalmatrix;
6598
6599         CHECKGLERROR
6600 }
6601
6602 void R_RenderWaterPlanes(void)
6603 {
6604         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6605         {
6606                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6607                 if (r_timereport_active)
6608                         R_TimeReport("waterworld");
6609         }
6610
6611         // don't let sound skip if going slow
6612         if (r_refdef.scene.extraupdate)
6613                 S_ExtraUpdate ();
6614
6615         R_DrawModelsAddWaterPlanes();
6616         if (r_timereport_active)
6617                 R_TimeReport("watermodels");
6618
6619         if (r_waterstate.numwaterplanes)
6620         {
6621                 R_Water_ProcessPlanes();
6622                 if (r_timereport_active)
6623                         R_TimeReport("waterscenes");
6624         }
6625 }
6626
6627 extern void R_DrawLightningBeams (void);
6628 extern void VM_CL_AddPolygonsToMeshQueue (void);
6629 extern void R_DrawPortals (void);
6630 extern cvar_t cl_locs_show;
6631 static void R_DrawLocs(void);
6632 static void R_DrawEntityBBoxes(void);
6633 static void R_DrawModelDecals(void);
6634 extern void R_DrawModelShadows(void);
6635 extern void R_DrawModelShadowMaps(void);
6636 extern cvar_t cl_decals_newsystem;
6637 extern qboolean r_shadow_usingdeferredprepass;
6638 void R_RenderScene(void)
6639 {
6640         qboolean shadowmapping = false;
6641
6642         if (r_timereport_active)
6643                 R_TimeReport("beginscene");
6644
6645         r_refdef.stats.renders++;
6646
6647         R_UpdateFogColor();
6648
6649         // don't let sound skip if going slow
6650         if (r_refdef.scene.extraupdate)
6651                 S_ExtraUpdate ();
6652
6653         R_MeshQueue_BeginScene();
6654
6655         R_SkyStartFrame();
6656
6657         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);
6658
6659         if (r_timereport_active)
6660                 R_TimeReport("skystartframe");
6661
6662         if (cl.csqc_vidvars.drawworld)
6663         {
6664                 // don't let sound skip if going slow
6665                 if (r_refdef.scene.extraupdate)
6666                         S_ExtraUpdate ();
6667
6668                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6669                 {
6670                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6671                         if (r_timereport_active)
6672                                 R_TimeReport("worldsky");
6673                 }
6674
6675                 if (R_DrawBrushModelsSky() && r_timereport_active)
6676                         R_TimeReport("bmodelsky");
6677
6678                 if (skyrendermasked && skyrenderlater)
6679                 {
6680                         // we have to force off the water clipping plane while rendering sky
6681                         R_SetupView(false);
6682                         R_Sky();
6683                         R_SetupView(true);
6684                         if (r_timereport_active)
6685                                 R_TimeReport("sky");
6686                 }
6687         }
6688
6689         R_AnimCache_CacheVisibleEntities();
6690         if (r_timereport_active)
6691                 R_TimeReport("animation");
6692
6693         R_Shadow_PrepareLights();
6694         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6695                 R_Shadow_PrepareModelShadows();
6696         if (r_timereport_active)
6697                 R_TimeReport("preparelights");
6698
6699         if (R_Shadow_ShadowMappingEnabled())
6700                 shadowmapping = true;
6701
6702         if (r_shadow_usingdeferredprepass)
6703                 R_Shadow_DrawPrepass();
6704
6705         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6706         {
6707                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6708                 if (r_timereport_active)
6709                         R_TimeReport("worlddepth");
6710         }
6711         if (r_depthfirst.integer >= 2)
6712         {
6713                 R_DrawModelsDepth();
6714                 if (r_timereport_active)
6715                         R_TimeReport("modeldepth");
6716         }
6717
6718         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6719         {
6720                 R_DrawModelShadowMaps();
6721                 R_ResetViewRendering3D();
6722                 // don't let sound skip if going slow
6723                 if (r_refdef.scene.extraupdate)
6724                         S_ExtraUpdate ();
6725         }
6726
6727         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6728         {
6729                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6730                 if (r_timereport_active)
6731                         R_TimeReport("world");
6732         }
6733
6734         // don't let sound skip if going slow
6735         if (r_refdef.scene.extraupdate)
6736                 S_ExtraUpdate ();
6737
6738         R_DrawModels();
6739         if (r_timereport_active)
6740                 R_TimeReport("models");
6741
6742         // don't let sound skip if going slow
6743         if (r_refdef.scene.extraupdate)
6744                 S_ExtraUpdate ();
6745
6746         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6747         {
6748                 R_DrawModelShadows();
6749                 R_ResetViewRendering3D();
6750                 // don't let sound skip if going slow
6751                 if (r_refdef.scene.extraupdate)
6752                         S_ExtraUpdate ();
6753         }
6754
6755         if (!r_shadow_usingdeferredprepass)
6756         {
6757                 R_Shadow_DrawLights();
6758                 if (r_timereport_active)
6759                         R_TimeReport("rtlights");
6760         }
6761
6762         // don't let sound skip if going slow
6763         if (r_refdef.scene.extraupdate)
6764                 S_ExtraUpdate ();
6765
6766         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6767         {
6768                 R_DrawModelShadows();
6769                 R_ResetViewRendering3D();
6770                 // don't let sound skip if going slow
6771                 if (r_refdef.scene.extraupdate)
6772                         S_ExtraUpdate ();
6773         }
6774
6775         if (cl.csqc_vidvars.drawworld)
6776         {
6777                 if (cl_decals_newsystem.integer)
6778                 {
6779                         R_DrawModelDecals();
6780                         if (r_timereport_active)
6781                                 R_TimeReport("modeldecals");
6782                 }
6783                 else
6784                 {
6785                         R_DrawDecals();
6786                         if (r_timereport_active)
6787                                 R_TimeReport("decals");
6788                 }
6789
6790                 R_DrawParticles();
6791                 if (r_timereport_active)
6792                         R_TimeReport("particles");
6793
6794                 R_DrawExplosions();
6795                 if (r_timereport_active)
6796                         R_TimeReport("explosions");
6797
6798                 R_DrawLightningBeams();
6799                 if (r_timereport_active)
6800                         R_TimeReport("lightning");
6801         }
6802
6803         VM_CL_AddPolygonsToMeshQueue();
6804
6805         if (r_refdef.view.showdebug)
6806         {
6807                 if (cl_locs_show.integer)
6808                 {
6809                         R_DrawLocs();
6810                         if (r_timereport_active)
6811                                 R_TimeReport("showlocs");
6812                 }
6813
6814                 if (r_drawportals.integer)
6815                 {
6816                         R_DrawPortals();
6817                         if (r_timereport_active)
6818                                 R_TimeReport("portals");
6819                 }
6820
6821                 if (r_showbboxes.value > 0)
6822                 {
6823                         R_DrawEntityBBoxes();
6824                         if (r_timereport_active)
6825                                 R_TimeReport("bboxes");
6826                 }
6827         }
6828
6829         R_MeshQueue_RenderTransparent();
6830         if (r_timereport_active)
6831                 R_TimeReport("drawtrans");
6832
6833         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))
6834         {
6835                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6836                 if (r_timereport_active)
6837                         R_TimeReport("worlddebug");
6838                 R_DrawModelsDebug();
6839                 if (r_timereport_active)
6840                         R_TimeReport("modeldebug");
6841         }
6842
6843         if (cl.csqc_vidvars.drawworld)
6844         {
6845                 R_Shadow_DrawCoronas();
6846                 if (r_timereport_active)
6847                         R_TimeReport("coronas");
6848         }
6849
6850 #if 0
6851         {
6852                 GL_DepthTest(false);
6853                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6854                 GL_Color(1, 1, 1, 1);
6855                 qglBegin(GL_POLYGON);
6856                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6857                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6858                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6859                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6860                 qglEnd();
6861                 qglBegin(GL_POLYGON);
6862                 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]);
6863                 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]);
6864                 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]);
6865                 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]);
6866                 qglEnd();
6867                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6868         }
6869 #endif
6870
6871         // don't let sound skip if going slow
6872         if (r_refdef.scene.extraupdate)
6873                 S_ExtraUpdate ();
6874
6875         R_ResetViewRendering2D();
6876 }
6877
6878 static const unsigned short bboxelements[36] =
6879 {
6880         5, 1, 3, 5, 3, 7,
6881         6, 2, 0, 6, 0, 4,
6882         7, 3, 2, 7, 2, 6,
6883         4, 0, 1, 4, 1, 5,
6884         4, 5, 7, 4, 7, 6,
6885         1, 0, 2, 1, 2, 3,
6886 };
6887
6888 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6889 {
6890         int i;
6891         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6892
6893         RSurf_ActiveWorldEntity();
6894
6895         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6896         GL_DepthMask(false);
6897         GL_DepthRange(0, 1);
6898         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6899 //      R_Mesh_ResetTextureState();
6900
6901         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6902         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6903         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6904         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6905         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6906         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6907         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6908         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6909         R_FillColors(color4f, 8, cr, cg, cb, ca);
6910         if (r_refdef.fogenabled)
6911         {
6912                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6913                 {
6914                         f1 = RSurf_FogVertex(v);
6915                         f2 = 1 - f1;
6916                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6917                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6918                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6919                 }
6920         }
6921         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6922         R_Mesh_ResetTextureState();
6923         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6924         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6925 }
6926
6927 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6928 {
6929         int i;
6930         float color[4];
6931         prvm_edict_t *edict;
6932         prvm_prog_t *prog_save = prog;
6933
6934         // this function draws bounding boxes of server entities
6935         if (!sv.active)
6936                 return;
6937
6938         GL_CullFace(GL_NONE);
6939         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6940
6941         prog = 0;
6942         SV_VM_Begin();
6943         for (i = 0;i < numsurfaces;i++)
6944         {
6945                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6946                 switch ((int)edict->fields.server->solid)
6947                 {
6948                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6949                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6950                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6951                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6952                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6953                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6954                 }
6955                 color[3] *= r_showbboxes.value;
6956                 color[3] = bound(0, color[3], 1);
6957                 GL_DepthTest(!r_showdisabledepthtest.integer);
6958                 GL_CullFace(r_refdef.view.cullface_front);
6959                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6960         }
6961         SV_VM_End();
6962         prog = prog_save;
6963 }
6964
6965 static void R_DrawEntityBBoxes(void)
6966 {
6967         int i;
6968         prvm_edict_t *edict;
6969         vec3_t center;
6970         prvm_prog_t *prog_save = prog;
6971
6972         // this function draws bounding boxes of server entities
6973         if (!sv.active)
6974                 return;
6975
6976         prog = 0;
6977         SV_VM_Begin();
6978         for (i = 0;i < prog->num_edicts;i++)
6979         {
6980                 edict = PRVM_EDICT_NUM(i);
6981                 if (edict->priv.server->free)
6982                         continue;
6983                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6984                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6985                         continue;
6986                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6987                         continue;
6988                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6989                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6990         }
6991         SV_VM_End();
6992         prog = prog_save;
6993 }
6994
6995 static const int nomodelelement3i[24] =
6996 {
6997         5, 2, 0,
6998         5, 1, 2,
6999         5, 0, 3,
7000         5, 3, 1,
7001         0, 2, 4,
7002         2, 1, 4,
7003         3, 0, 4,
7004         1, 3, 4
7005 };
7006
7007 static const unsigned short nomodelelement3s[24] =
7008 {
7009         5, 2, 0,
7010         5, 1, 2,
7011         5, 0, 3,
7012         5, 3, 1,
7013         0, 2, 4,
7014         2, 1, 4,
7015         3, 0, 4,
7016         1, 3, 4
7017 };
7018
7019 static const float nomodelvertex3f[6*3] =
7020 {
7021         -16,   0,   0,
7022          16,   0,   0,
7023           0, -16,   0,
7024           0,  16,   0,
7025           0,   0, -16,
7026           0,   0,  16
7027 };
7028
7029 static const float nomodelcolor4f[6*4] =
7030 {
7031         0.0f, 0.0f, 0.5f, 1.0f,
7032         0.0f, 0.0f, 0.5f, 1.0f,
7033         0.0f, 0.5f, 0.0f, 1.0f,
7034         0.0f, 0.5f, 0.0f, 1.0f,
7035         0.5f, 0.0f, 0.0f, 1.0f,
7036         0.5f, 0.0f, 0.0f, 1.0f
7037 };
7038
7039 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7040 {
7041         int i;
7042         float f1, f2, *c;
7043         float color4f[6*4];
7044
7045         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);
7046
7047         // this is only called once per entity so numsurfaces is always 1, and
7048         // surfacelist is always {0}, so this code does not handle batches
7049
7050         if (rsurface.ent_flags & RENDER_ADDITIVE)
7051         {
7052                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7053                 GL_DepthMask(false);
7054         }
7055         else if (rsurface.colormod[3] < 1)
7056         {
7057                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7058                 GL_DepthMask(false);
7059         }
7060         else
7061         {
7062                 GL_BlendFunc(GL_ONE, GL_ZERO);
7063                 GL_DepthMask(true);
7064         }
7065         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7066         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7067         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7068         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7069         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7070         for (i = 0, c = color4f;i < 6;i++, c += 4)
7071         {
7072                 c[0] *= rsurface.colormod[0];
7073                 c[1] *= rsurface.colormod[1];
7074                 c[2] *= rsurface.colormod[2];
7075                 c[3] *= rsurface.colormod[3];
7076         }
7077         if (r_refdef.fogenabled)
7078         {
7079                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7080                 {
7081                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7082                         f2 = 1 - f1;
7083                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7084                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7085                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7086                 }
7087         }
7088 //      R_Mesh_ResetTextureState();
7089         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7090         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7091         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7092 }
7093
7094 void R_DrawNoModel(entity_render_t *ent)
7095 {
7096         vec3_t org;
7097         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7098         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7099                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7100         else
7101                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7102 }
7103
7104 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7105 {
7106         vec3_t right1, right2, diff, normal;
7107
7108         VectorSubtract (org2, org1, normal);
7109
7110         // calculate 'right' vector for start
7111         VectorSubtract (r_refdef.view.origin, org1, diff);
7112         CrossProduct (normal, diff, right1);
7113         VectorNormalize (right1);
7114
7115         // calculate 'right' vector for end
7116         VectorSubtract (r_refdef.view.origin, org2, diff);
7117         CrossProduct (normal, diff, right2);
7118         VectorNormalize (right2);
7119
7120         vert[ 0] = org1[0] + width * right1[0];
7121         vert[ 1] = org1[1] + width * right1[1];
7122         vert[ 2] = org1[2] + width * right1[2];
7123         vert[ 3] = org1[0] - width * right1[0];
7124         vert[ 4] = org1[1] - width * right1[1];
7125         vert[ 5] = org1[2] - width * right1[2];
7126         vert[ 6] = org2[0] - width * right2[0];
7127         vert[ 7] = org2[1] - width * right2[1];
7128         vert[ 8] = org2[2] - width * right2[2];
7129         vert[ 9] = org2[0] + width * right2[0];
7130         vert[10] = org2[1] + width * right2[1];
7131         vert[11] = org2[2] + width * right2[2];
7132 }
7133
7134 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)
7135 {
7136         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7137         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7138         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7139         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7140         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7141         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7142         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7143         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7144         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7145         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7146         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7147         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7148 }
7149
7150 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7151 {
7152         int i;
7153         float *vertex3f;
7154         float v[3];
7155         VectorSet(v, x, y, z);
7156         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7157                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7158                         break;
7159         if (i == mesh->numvertices)
7160         {
7161                 if (mesh->numvertices < mesh->maxvertices)
7162                 {
7163                         VectorCopy(v, vertex3f);
7164                         mesh->numvertices++;
7165                 }
7166                 return mesh->numvertices;
7167         }
7168         else
7169                 return i;
7170 }
7171
7172 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7173 {
7174         int i;
7175         int *e, element[3];
7176         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7177         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7178         e = mesh->element3i + mesh->numtriangles * 3;
7179         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7180         {
7181                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7182                 if (mesh->numtriangles < mesh->maxtriangles)
7183                 {
7184                         *e++ = element[0];
7185                         *e++ = element[1];
7186                         *e++ = element[2];
7187                         mesh->numtriangles++;
7188                 }
7189                 element[1] = element[2];
7190         }
7191 }
7192
7193 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7194 {
7195         int i;
7196         int *e, element[3];
7197         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7198         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7199         e = mesh->element3i + mesh->numtriangles * 3;
7200         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7201         {
7202                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7203                 if (mesh->numtriangles < mesh->maxtriangles)
7204                 {
7205                         *e++ = element[0];
7206                         *e++ = element[1];
7207                         *e++ = element[2];
7208                         mesh->numtriangles++;
7209                 }
7210                 element[1] = element[2];
7211         }
7212 }
7213
7214 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7215 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7216 {
7217         int planenum, planenum2;
7218         int w;
7219         int tempnumpoints;
7220         mplane_t *plane, *plane2;
7221         double maxdist;
7222         double temppoints[2][256*3];
7223         // figure out how large a bounding box we need to properly compute this brush
7224         maxdist = 0;
7225         for (w = 0;w < numplanes;w++)
7226                 maxdist = max(maxdist, fabs(planes[w].dist));
7227         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7228         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7229         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7230         {
7231                 w = 0;
7232                 tempnumpoints = 4;
7233                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7234                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7235                 {
7236                         if (planenum2 == planenum)
7237                                 continue;
7238                         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);
7239                         w = !w;
7240                 }
7241                 if (tempnumpoints < 3)
7242                         continue;
7243                 // generate elements forming a triangle fan for this polygon
7244                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7245         }
7246 }
7247
7248 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)
7249 {
7250         texturelayer_t *layer;
7251         layer = t->currentlayers + t->currentnumlayers++;
7252         layer->type = type;
7253         layer->depthmask = depthmask;
7254         layer->blendfunc1 = blendfunc1;
7255         layer->blendfunc2 = blendfunc2;
7256         layer->texture = texture;
7257         layer->texmatrix = *matrix;
7258         layer->color[0] = r;
7259         layer->color[1] = g;
7260         layer->color[2] = b;
7261         layer->color[3] = a;
7262 }
7263
7264 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7265 {
7266         if(parms[0] == 0 && parms[1] == 0)
7267                 return false;
7268         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7269                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7270                         return false;
7271         return true;
7272 }
7273
7274 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7275 {
7276         double index, f;
7277         index = parms[2] + r_refdef.scene.time * parms[3];
7278         index -= floor(index);
7279         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7280         {
7281         default:
7282         case Q3WAVEFUNC_NONE:
7283         case Q3WAVEFUNC_NOISE:
7284         case Q3WAVEFUNC_COUNT:
7285                 f = 0;
7286                 break;
7287         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7288         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7289         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7290         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7291         case Q3WAVEFUNC_TRIANGLE:
7292                 index *= 4;
7293                 f = index - floor(index);
7294                 if (index < 1)
7295                         f = f;
7296                 else if (index < 2)
7297                         f = 1 - f;
7298                 else if (index < 3)
7299                         f = -f;
7300                 else
7301                         f = -(1 - f);
7302                 break;
7303         }
7304         f = parms[0] + parms[1] * f;
7305         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7306                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7307         return (float) f;
7308 }
7309
7310 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7311 {
7312         int w, h, idx;
7313         float f;
7314         float tcmat[12];
7315         matrix4x4_t matrix, temp;
7316         switch(tcmod->tcmod)
7317         {
7318                 case Q3TCMOD_COUNT:
7319                 case Q3TCMOD_NONE:
7320                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7321                                 matrix = r_waterscrollmatrix;
7322                         else
7323                                 matrix = identitymatrix;
7324                         break;
7325                 case Q3TCMOD_ENTITYTRANSLATE:
7326                         // this is used in Q3 to allow the gamecode to control texcoord
7327                         // scrolling on the entity, which is not supported in darkplaces yet.
7328                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7329                         break;
7330                 case Q3TCMOD_ROTATE:
7331                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7332                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7333                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7334                         break;
7335                 case Q3TCMOD_SCALE:
7336                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7337                         break;
7338                 case Q3TCMOD_SCROLL:
7339                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7340                         break;
7341                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7342                         w = (int) tcmod->parms[0];
7343                         h = (int) tcmod->parms[1];
7344                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7345                         f = f - floor(f);
7346                         idx = (int) floor(f * w * h);
7347                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7348                         break;
7349                 case Q3TCMOD_STRETCH:
7350                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7351                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7352                         break;
7353                 case Q3TCMOD_TRANSFORM:
7354                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7355                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7356                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7357                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7358                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7359                         break;
7360                 case Q3TCMOD_TURBULENT:
7361                         // this is handled in the RSurf_PrepareVertices function
7362                         matrix = identitymatrix;
7363                         break;
7364         }
7365         temp = *texmatrix;
7366         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7367 }
7368
7369 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7370 {
7371         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7372         char name[MAX_QPATH];
7373         skinframe_t *skinframe;
7374         unsigned char pixels[296*194];
7375         strlcpy(cache->name, skinname, sizeof(cache->name));
7376         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7377         if (developer_loading.integer)
7378                 Con_Printf("loading %s\n", name);
7379         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7380         if (!skinframe || !skinframe->base)
7381         {
7382                 unsigned char *f;
7383                 fs_offset_t filesize;
7384                 skinframe = NULL;
7385                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7386                 if (f)
7387                 {
7388                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7389                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7390                         Mem_Free(f);
7391                 }
7392         }
7393         cache->skinframe = skinframe;
7394 }
7395
7396 texture_t *R_GetCurrentTexture(texture_t *t)
7397 {
7398         int i;
7399         const entity_render_t *ent = rsurface.entity;
7400         dp_model_t *model = ent->model;
7401         q3shaderinfo_layer_tcmod_t *tcmod;
7402
7403         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7404                 return t->currentframe;
7405         t->update_lastrenderframe = r_textureframe;
7406         t->update_lastrenderentity = (void *)ent;
7407
7408         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7409                 t->camera_entity = ent->entitynumber;
7410         else
7411                 t->camera_entity = 0;
7412
7413         // switch to an alternate material if this is a q1bsp animated material
7414         {
7415                 texture_t *texture = t;
7416                 int s = rsurface.ent_skinnum;
7417                 if ((unsigned int)s >= (unsigned int)model->numskins)
7418                         s = 0;
7419                 if (model->skinscenes)
7420                 {
7421                         if (model->skinscenes[s].framecount > 1)
7422                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7423                         else
7424                                 s = model->skinscenes[s].firstframe;
7425                 }
7426                 if (s > 0)
7427                         t = t + s * model->num_surfaces;
7428                 if (t->animated)
7429                 {
7430                         // use an alternate animation if the entity's frame is not 0,
7431                         // and only if the texture has an alternate animation
7432                         if (rsurface.ent_alttextures && t->anim_total[1])
7433                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7434                         else
7435                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7436                 }
7437                 texture->currentframe = t;
7438         }
7439
7440         // update currentskinframe to be a qw skin or animation frame
7441         if (rsurface.ent_qwskin >= 0)
7442         {
7443                 i = rsurface.ent_qwskin;
7444                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7445                 {
7446                         r_qwskincache_size = cl.maxclients;
7447                         if (r_qwskincache)
7448                                 Mem_Free(r_qwskincache);
7449                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7450                 }
7451                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7452                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7453                 t->currentskinframe = r_qwskincache[i].skinframe;
7454                 if (t->currentskinframe == NULL)
7455                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7456         }
7457         else if (t->numskinframes >= 2)
7458                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7459         if (t->backgroundnumskinframes >= 2)
7460                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7461
7462         t->currentmaterialflags = t->basematerialflags;
7463         t->currentalpha = rsurface.colormod[3];
7464         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7465                 t->currentalpha *= r_wateralpha.value;
7466         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7467                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7468         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7469                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7470         if (!(rsurface.ent_flags & RENDER_LIGHT))
7471                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7472         else if (FAKELIGHT_ENABLED)
7473         {
7474                         // no modellight if using fakelight for the map
7475         }
7476         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7477         {
7478                 // pick a model lighting mode
7479                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7480                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7481                 else
7482                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7483         }
7484         if (rsurface.ent_flags & RENDER_ADDITIVE)
7485                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7486         else if (t->currentalpha < 1)
7487                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7488         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7489                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7490         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7491                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7492         if (t->backgroundnumskinframes)
7493                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7494         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7495         {
7496                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7497                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7498         }
7499         else
7500                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7501         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7502                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7503
7504         // there is no tcmod
7505         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7506         {
7507                 t->currenttexmatrix = r_waterscrollmatrix;
7508                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7509         }
7510         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7511         {
7512                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7513                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7514         }
7515
7516         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7517                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7518         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7519                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7520
7521         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7522         if (t->currentskinframe->qpixels)
7523                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7524         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7525         if (!t->basetexture)
7526                 t->basetexture = r_texture_notexture;
7527         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7528         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7529         t->nmaptexture = t->currentskinframe->nmap;
7530         if (!t->nmaptexture)
7531                 t->nmaptexture = r_texture_blanknormalmap;
7532         t->glosstexture = r_texture_black;
7533         t->glowtexture = t->currentskinframe->glow;
7534         t->fogtexture = t->currentskinframe->fog;
7535         t->reflectmasktexture = t->currentskinframe->reflect;
7536         if (t->backgroundnumskinframes)
7537         {
7538                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7539                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7540                 t->backgroundglosstexture = r_texture_black;
7541                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7542                 if (!t->backgroundnmaptexture)
7543                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7544         }
7545         else
7546         {
7547                 t->backgroundbasetexture = r_texture_white;
7548                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7549                 t->backgroundglosstexture = r_texture_black;
7550                 t->backgroundglowtexture = NULL;
7551         }
7552         t->specularpower = r_shadow_glossexponent.value;
7553         // TODO: store reference values for these in the texture?
7554         t->specularscale = 0;
7555         if (r_shadow_gloss.integer > 0)
7556         {
7557                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7558                 {
7559                         if (r_shadow_glossintensity.value > 0)
7560                         {
7561                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7562                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7563                                 t->specularscale = r_shadow_glossintensity.value;
7564                         }
7565                 }
7566                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7567                 {
7568                         t->glosstexture = r_texture_white;
7569                         t->backgroundglosstexture = r_texture_white;
7570                         t->specularscale = r_shadow_gloss2intensity.value;
7571                         t->specularpower = r_shadow_gloss2exponent.value;
7572                 }
7573         }
7574         t->specularscale *= t->specularscalemod;
7575         t->specularpower *= t->specularpowermod;
7576
7577         // lightmaps mode looks bad with dlights using actual texturing, so turn
7578         // off the colormap and glossmap, but leave the normalmap on as it still
7579         // accurately represents the shading involved
7580         if (gl_lightmaps.integer)
7581         {
7582                 t->basetexture = r_texture_grey128;
7583                 t->pantstexture = r_texture_black;
7584                 t->shirttexture = r_texture_black;
7585                 t->nmaptexture = r_texture_blanknormalmap;
7586                 t->glosstexture = r_texture_black;
7587                 t->glowtexture = NULL;
7588                 t->fogtexture = NULL;
7589                 t->reflectmasktexture = NULL;
7590                 t->backgroundbasetexture = NULL;
7591                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7592                 t->backgroundglosstexture = r_texture_black;
7593                 t->backgroundglowtexture = NULL;
7594                 t->specularscale = 0;
7595                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7596         }
7597
7598         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7599         VectorClear(t->dlightcolor);
7600         t->currentnumlayers = 0;
7601         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7602         {
7603                 int blendfunc1, blendfunc2;
7604                 qboolean depthmask;
7605                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7606                 {
7607                         blendfunc1 = GL_SRC_ALPHA;
7608                         blendfunc2 = GL_ONE;
7609                 }
7610                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7611                 {
7612                         blendfunc1 = GL_SRC_ALPHA;
7613                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7614                 }
7615                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7616                 {
7617                         blendfunc1 = t->customblendfunc[0];
7618                         blendfunc2 = t->customblendfunc[1];
7619                 }
7620                 else
7621                 {
7622                         blendfunc1 = GL_ONE;
7623                         blendfunc2 = GL_ZERO;
7624                 }
7625                 // don't colormod evilblend textures
7626                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
7627                         VectorSet(t->lightmapcolor, 1, 1, 1);
7628                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7629                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7630                 {
7631                         // fullbright is not affected by r_refdef.lightmapintensity
7632                         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]);
7633                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7634                                 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]);
7635                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7636                                 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]);
7637                 }
7638                 else
7639                 {
7640                         vec3_t ambientcolor;
7641                         float colorscale;
7642                         // set the color tint used for lights affecting this surface
7643                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7644                         colorscale = 2;
7645                         // q3bsp has no lightmap updates, so the lightstylevalue that
7646                         // would normally be baked into the lightmap must be
7647                         // applied to the color
7648                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7649                         if (model->type == mod_brushq3)
7650                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7651                         colorscale *= r_refdef.lightmapintensity;
7652                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7653                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7654                         // basic lit geometry
7655                         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]);
7656                         // add pants/shirt if needed
7657                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7658                                 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]);
7659                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7660                                 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]);
7661                         // now add ambient passes if needed
7662                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7663                         {
7664                                 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]);
7665                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7666                                         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]);
7667                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7668                                         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]);
7669                         }
7670                 }
7671                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7672                         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]);
7673                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7674                 {
7675                         // if this is opaque use alpha blend which will darken the earlier
7676                         // passes cheaply.
7677                         //
7678                         // if this is an alpha blended material, all the earlier passes
7679                         // were darkened by fog already, so we only need to add the fog
7680                         // color ontop through the fog mask texture
7681                         //
7682                         // if this is an additive blended material, all the earlier passes
7683                         // were darkened by fog already, and we should not add fog color
7684                         // (because the background was not darkened, there is no fog color
7685                         // that was lost behind it).
7686                         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]);
7687                 }
7688         }
7689
7690         return t->currentframe;
7691 }
7692
7693 rsurfacestate_t rsurface;
7694
7695 void RSurf_ActiveWorldEntity(void)
7696 {
7697         dp_model_t *model = r_refdef.scene.worldmodel;
7698         //if (rsurface.entity == r_refdef.scene.worldentity)
7699         //      return;
7700         rsurface.entity = r_refdef.scene.worldentity;
7701         rsurface.skeleton = NULL;
7702         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7703         rsurface.ent_skinnum = 0;
7704         rsurface.ent_qwskin = -1;
7705         rsurface.ent_shadertime = 0;
7706         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7707         rsurface.matrix = identitymatrix;
7708         rsurface.inversematrix = identitymatrix;
7709         rsurface.matrixscale = 1;
7710         rsurface.inversematrixscale = 1;
7711         R_EntityMatrix(&identitymatrix);
7712         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7713         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7714         rsurface.fograngerecip = r_refdef.fograngerecip;
7715         rsurface.fogheightfade = r_refdef.fogheightfade;
7716         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7717         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7718         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7719         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7720         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7721         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7722         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7723         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7724         rsurface.colormod[3] = 1;
7725         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);
7726         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7727         rsurface.frameblend[0].lerp = 1;
7728         rsurface.ent_alttextures = false;
7729         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7730         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7731         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7732         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7733         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7734         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7735         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7736         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7737         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7738         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7739         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7740         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7741         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7742         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7743         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7744         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7745         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7746         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7747         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7748         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7749         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7750         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7751         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7752         rsurface.modelelement3i = model->surfmesh.data_element3i;
7753         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7754         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7755         rsurface.modelelement3s = model->surfmesh.data_element3s;
7756         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7757         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7758         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7759         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7760         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7761         rsurface.modelsurfaces = model->data_surfaces;
7762         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7763         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7764         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7765         rsurface.modelgeneratedvertex = false;
7766         rsurface.batchgeneratedvertex = false;
7767         rsurface.batchfirstvertex = 0;
7768         rsurface.batchnumvertices = 0;
7769         rsurface.batchfirsttriangle = 0;
7770         rsurface.batchnumtriangles = 0;
7771         rsurface.batchvertex3f  = NULL;
7772         rsurface.batchvertex3f_vertexbuffer = NULL;
7773         rsurface.batchvertex3f_bufferoffset = 0;
7774         rsurface.batchsvector3f = NULL;
7775         rsurface.batchsvector3f_vertexbuffer = NULL;
7776         rsurface.batchsvector3f_bufferoffset = 0;
7777         rsurface.batchtvector3f = NULL;
7778         rsurface.batchtvector3f_vertexbuffer = NULL;
7779         rsurface.batchtvector3f_bufferoffset = 0;
7780         rsurface.batchnormal3f  = NULL;
7781         rsurface.batchnormal3f_vertexbuffer = NULL;
7782         rsurface.batchnormal3f_bufferoffset = 0;
7783         rsurface.batchlightmapcolor4f = NULL;
7784         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7785         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7786         rsurface.batchtexcoordtexture2f = NULL;
7787         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7788         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7789         rsurface.batchtexcoordlightmap2f = NULL;
7790         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7791         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7792         rsurface.batchvertexmesh = NULL;
7793         rsurface.batchvertexmeshbuffer = NULL;
7794         rsurface.batchvertex3fbuffer = NULL;
7795         rsurface.batchelement3i = NULL;
7796         rsurface.batchelement3i_indexbuffer = NULL;
7797         rsurface.batchelement3i_bufferoffset = 0;
7798         rsurface.batchelement3s = NULL;
7799         rsurface.batchelement3s_indexbuffer = NULL;
7800         rsurface.batchelement3s_bufferoffset = 0;
7801         rsurface.passcolor4f = NULL;
7802         rsurface.passcolor4f_vertexbuffer = NULL;
7803         rsurface.passcolor4f_bufferoffset = 0;
7804 }
7805
7806 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7807 {
7808         dp_model_t *model = ent->model;
7809         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7810         //      return;
7811         rsurface.entity = (entity_render_t *)ent;
7812         rsurface.skeleton = ent->skeleton;
7813         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7814         rsurface.ent_skinnum = ent->skinnum;
7815         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;
7816         rsurface.ent_shadertime = ent->shadertime;
7817         rsurface.ent_flags = ent->flags;
7818         rsurface.matrix = ent->matrix;
7819         rsurface.inversematrix = ent->inversematrix;
7820         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7821         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7822         R_EntityMatrix(&rsurface.matrix);
7823         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7824         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7825         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7826         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7827         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7828         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7829         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7830         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7831         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7832         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7833         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7834         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7835         rsurface.colormod[3] = ent->alpha;
7836         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7837         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7838         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7839         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7840         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7841         if (ent->model->brush.submodel && !prepass)
7842         {
7843                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7844                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7845         }
7846         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7847         {
7848                 if (ent->animcache_vertex3f)
7849                 {
7850                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7851                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7852                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7853                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7854                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7855                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7856                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7857                 }
7858                 else if (wanttangents)
7859                 {
7860                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7861                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7862                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7863                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7864                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7865                         rsurface.modelvertexmesh = NULL;
7866                         rsurface.modelvertexmeshbuffer = NULL;
7867                         rsurface.modelvertex3fbuffer = NULL;
7868                 }
7869                 else if (wantnormals)
7870                 {
7871                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7872                         rsurface.modelsvector3f = NULL;
7873                         rsurface.modeltvector3f = NULL;
7874                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7875                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7876                         rsurface.modelvertexmesh = NULL;
7877                         rsurface.modelvertexmeshbuffer = NULL;
7878                         rsurface.modelvertex3fbuffer = NULL;
7879                 }
7880                 else
7881                 {
7882                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7883                         rsurface.modelsvector3f = NULL;
7884                         rsurface.modeltvector3f = NULL;
7885                         rsurface.modelnormal3f = NULL;
7886                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7887                         rsurface.modelvertexmesh = NULL;
7888                         rsurface.modelvertexmeshbuffer = NULL;
7889                         rsurface.modelvertex3fbuffer = NULL;
7890                 }
7891                 rsurface.modelvertex3f_vertexbuffer = 0;
7892                 rsurface.modelvertex3f_bufferoffset = 0;
7893                 rsurface.modelsvector3f_vertexbuffer = 0;
7894                 rsurface.modelsvector3f_bufferoffset = 0;
7895                 rsurface.modeltvector3f_vertexbuffer = 0;
7896                 rsurface.modeltvector3f_bufferoffset = 0;
7897                 rsurface.modelnormal3f_vertexbuffer = 0;
7898                 rsurface.modelnormal3f_bufferoffset = 0;
7899                 rsurface.modelgeneratedvertex = true;
7900         }
7901         else
7902         {
7903                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7904                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7905                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7906                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7907                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7908                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7909                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7910                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7911                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7912                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7913                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7914                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7915                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7916                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7917                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7918                 rsurface.modelgeneratedvertex = false;
7919         }
7920         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7921         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7922         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7923         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7924         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7925         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7926         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7927         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7929         rsurface.modelelement3i = model->surfmesh.data_element3i;
7930         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7931         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7932         rsurface.modelelement3s = model->surfmesh.data_element3s;
7933         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7934         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7935         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7936         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7937         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7938         rsurface.modelsurfaces = model->data_surfaces;
7939         rsurface.batchgeneratedvertex = false;
7940         rsurface.batchfirstvertex = 0;
7941         rsurface.batchnumvertices = 0;
7942         rsurface.batchfirsttriangle = 0;
7943         rsurface.batchnumtriangles = 0;
7944         rsurface.batchvertex3f  = NULL;
7945         rsurface.batchvertex3f_vertexbuffer = NULL;
7946         rsurface.batchvertex3f_bufferoffset = 0;
7947         rsurface.batchsvector3f = NULL;
7948         rsurface.batchsvector3f_vertexbuffer = NULL;
7949         rsurface.batchsvector3f_bufferoffset = 0;
7950         rsurface.batchtvector3f = NULL;
7951         rsurface.batchtvector3f_vertexbuffer = NULL;
7952         rsurface.batchtvector3f_bufferoffset = 0;
7953         rsurface.batchnormal3f  = NULL;
7954         rsurface.batchnormal3f_vertexbuffer = NULL;
7955         rsurface.batchnormal3f_bufferoffset = 0;
7956         rsurface.batchlightmapcolor4f = NULL;
7957         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7958         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7959         rsurface.batchtexcoordtexture2f = NULL;
7960         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7961         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7962         rsurface.batchtexcoordlightmap2f = NULL;
7963         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7964         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7965         rsurface.batchvertexmesh = NULL;
7966         rsurface.batchvertexmeshbuffer = NULL;
7967         rsurface.batchvertex3fbuffer = NULL;
7968         rsurface.batchelement3i = NULL;
7969         rsurface.batchelement3i_indexbuffer = NULL;
7970         rsurface.batchelement3i_bufferoffset = 0;
7971         rsurface.batchelement3s = NULL;
7972         rsurface.batchelement3s_indexbuffer = NULL;
7973         rsurface.batchelement3s_bufferoffset = 0;
7974         rsurface.passcolor4f = NULL;
7975         rsurface.passcolor4f_vertexbuffer = NULL;
7976         rsurface.passcolor4f_bufferoffset = 0;
7977 }
7978
7979 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)
7980 {
7981         rsurface.entity = r_refdef.scene.worldentity;
7982         rsurface.skeleton = NULL;
7983         rsurface.ent_skinnum = 0;
7984         rsurface.ent_qwskin = -1;
7985         rsurface.ent_shadertime = shadertime;
7986         rsurface.ent_flags = entflags;
7987         rsurface.modelnumvertices = numvertices;
7988         rsurface.modelnumtriangles = numtriangles;
7989         rsurface.matrix = *matrix;
7990         rsurface.inversematrix = *inversematrix;
7991         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7992         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7993         R_EntityMatrix(&rsurface.matrix);
7994         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7995         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7996         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7997         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7998         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7999         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8000         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8001         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8002         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8003         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8004         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8005         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8006         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);
8007         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8008         rsurface.frameblend[0].lerp = 1;
8009         rsurface.ent_alttextures = false;
8010         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8011         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8012         if (wanttangents)
8013         {
8014                 rsurface.modelvertex3f = (float *)vertex3f;
8015                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8016                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8017                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8018         }
8019         else if (wantnormals)
8020         {
8021                 rsurface.modelvertex3f = (float *)vertex3f;
8022                 rsurface.modelsvector3f = NULL;
8023                 rsurface.modeltvector3f = NULL;
8024                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8025         }
8026         else
8027         {
8028                 rsurface.modelvertex3f = (float *)vertex3f;
8029                 rsurface.modelsvector3f = NULL;
8030                 rsurface.modeltvector3f = NULL;
8031                 rsurface.modelnormal3f = NULL;
8032         }
8033         rsurface.modelvertexmesh = NULL;
8034         rsurface.modelvertexmeshbuffer = NULL;
8035         rsurface.modelvertex3fbuffer = NULL;
8036         rsurface.modelvertex3f_vertexbuffer = 0;
8037         rsurface.modelvertex3f_bufferoffset = 0;
8038         rsurface.modelsvector3f_vertexbuffer = 0;
8039         rsurface.modelsvector3f_bufferoffset = 0;
8040         rsurface.modeltvector3f_vertexbuffer = 0;
8041         rsurface.modeltvector3f_bufferoffset = 0;
8042         rsurface.modelnormal3f_vertexbuffer = 0;
8043         rsurface.modelnormal3f_bufferoffset = 0;
8044         rsurface.modelgeneratedvertex = true;
8045         rsurface.modellightmapcolor4f  = (float *)color4f;
8046         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8047         rsurface.modellightmapcolor4f_bufferoffset = 0;
8048         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8049         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8050         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8051         rsurface.modeltexcoordlightmap2f  = NULL;
8052         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8053         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8054         rsurface.modelelement3i = (int *)element3i;
8055         rsurface.modelelement3i_indexbuffer = NULL;
8056         rsurface.modelelement3i_bufferoffset = 0;
8057         rsurface.modelelement3s = (unsigned short *)element3s;
8058         rsurface.modelelement3s_indexbuffer = NULL;
8059         rsurface.modelelement3s_bufferoffset = 0;
8060         rsurface.modellightmapoffsets = NULL;
8061         rsurface.modelsurfaces = NULL;
8062         rsurface.batchgeneratedvertex = false;
8063         rsurface.batchfirstvertex = 0;
8064         rsurface.batchnumvertices = 0;
8065         rsurface.batchfirsttriangle = 0;
8066         rsurface.batchnumtriangles = 0;
8067         rsurface.batchvertex3f  = NULL;
8068         rsurface.batchvertex3f_vertexbuffer = NULL;
8069         rsurface.batchvertex3f_bufferoffset = 0;
8070         rsurface.batchsvector3f = NULL;
8071         rsurface.batchsvector3f_vertexbuffer = NULL;
8072         rsurface.batchsvector3f_bufferoffset = 0;
8073         rsurface.batchtvector3f = NULL;
8074         rsurface.batchtvector3f_vertexbuffer = NULL;
8075         rsurface.batchtvector3f_bufferoffset = 0;
8076         rsurface.batchnormal3f  = NULL;
8077         rsurface.batchnormal3f_vertexbuffer = NULL;
8078         rsurface.batchnormal3f_bufferoffset = 0;
8079         rsurface.batchlightmapcolor4f = NULL;
8080         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8081         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8082         rsurface.batchtexcoordtexture2f = NULL;
8083         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8084         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8085         rsurface.batchtexcoordlightmap2f = NULL;
8086         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8087         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8088         rsurface.batchvertexmesh = NULL;
8089         rsurface.batchvertexmeshbuffer = NULL;
8090         rsurface.batchvertex3fbuffer = NULL;
8091         rsurface.batchelement3i = NULL;
8092         rsurface.batchelement3i_indexbuffer = NULL;
8093         rsurface.batchelement3i_bufferoffset = 0;
8094         rsurface.batchelement3s = NULL;
8095         rsurface.batchelement3s_indexbuffer = NULL;
8096         rsurface.batchelement3s_bufferoffset = 0;
8097         rsurface.passcolor4f = NULL;
8098         rsurface.passcolor4f_vertexbuffer = NULL;
8099         rsurface.passcolor4f_bufferoffset = 0;
8100
8101         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8102         {
8103                 if ((wantnormals || wanttangents) && !normal3f)
8104                 {
8105                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8106                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8107                 }
8108                 if (wanttangents && !svector3f)
8109                 {
8110                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8111                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8112                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8113                 }
8114         }
8115 }
8116
8117 float RSurf_FogPoint(const float *v)
8118 {
8119         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8120         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8121         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8122         float FogHeightFade = r_refdef.fogheightfade;
8123         float fogfrac;
8124         unsigned int fogmasktableindex;
8125         if (r_refdef.fogplaneviewabove)
8126                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8127         else
8128                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8129         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8130         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8131 }
8132
8133 float RSurf_FogVertex(const float *v)
8134 {
8135         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8136         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8137         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8138         float FogHeightFade = rsurface.fogheightfade;
8139         float fogfrac;
8140         unsigned int fogmasktableindex;
8141         if (r_refdef.fogplaneviewabove)
8142                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8143         else
8144                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8145         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8146         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8147 }
8148
8149 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8150 {
8151         int i;
8152         for (i = 0;i < numelements;i++)
8153                 outelement3i[i] = inelement3i[i] + adjust;
8154 }
8155
8156 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8157 extern cvar_t gl_vbo;
8158 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8159 {
8160         int deformindex;
8161         int firsttriangle;
8162         int numtriangles;
8163         int firstvertex;
8164         int endvertex;
8165         int numvertices;
8166         int surfacefirsttriangle;
8167         int surfacenumtriangles;
8168         int surfacefirstvertex;
8169         int surfaceendvertex;
8170         int surfacenumvertices;
8171         int batchnumvertices;
8172         int batchnumtriangles;
8173         int needsupdate;
8174         int i, j;
8175         qboolean gaps;
8176         qboolean dynamicvertex;
8177         float amplitude;
8178         float animpos;
8179         float scale;
8180         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8181         float waveparms[4];
8182         q3shaderinfo_deform_t *deform;
8183         const msurface_t *surface, *firstsurface;
8184         r_vertexmesh_t *vertexmesh;
8185         if (!texturenumsurfaces)
8186                 return;
8187         // find vertex range of this surface batch
8188         gaps = false;
8189         firstsurface = texturesurfacelist[0];
8190         firsttriangle = firstsurface->num_firsttriangle;
8191         batchnumvertices = 0;
8192         batchnumtriangles = 0;
8193         firstvertex = endvertex = firstsurface->num_firstvertex;
8194         for (i = 0;i < texturenumsurfaces;i++)
8195         {
8196                 surface = texturesurfacelist[i];
8197                 if (surface != firstsurface + i)
8198                         gaps = true;
8199                 surfacefirstvertex = surface->num_firstvertex;
8200                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8201                 surfacenumvertices = surface->num_vertices;
8202                 surfacenumtriangles = surface->num_triangles;
8203                 if (firstvertex > surfacefirstvertex)
8204                         firstvertex = surfacefirstvertex;
8205                 if (endvertex < surfaceendvertex)
8206                         endvertex = surfaceendvertex;
8207                 batchnumvertices += surfacenumvertices;
8208                 batchnumtriangles += surfacenumtriangles;
8209         }
8210
8211         // we now know the vertex range used, and if there are any gaps in it
8212         rsurface.batchfirstvertex = firstvertex;
8213         rsurface.batchnumvertices = endvertex - firstvertex;
8214         rsurface.batchfirsttriangle = firsttriangle;
8215         rsurface.batchnumtriangles = batchnumtriangles;
8216
8217         // this variable holds flags for which properties have been updated that
8218         // may require regenerating vertexmesh array...
8219         needsupdate = 0;
8220
8221         // check if any dynamic vertex processing must occur
8222         dynamicvertex = false;
8223
8224         // if there is a chance of animated vertex colors, it's a dynamic batch
8225         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8226         {
8227                 dynamicvertex = true;
8228                 batchneed |= BATCHNEED_NOGAPS;
8229                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8230         }
8231
8232         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8233         {
8234                 switch (deform->deform)
8235                 {
8236                 default:
8237                 case Q3DEFORM_PROJECTIONSHADOW:
8238                 case Q3DEFORM_TEXT0:
8239                 case Q3DEFORM_TEXT1:
8240                 case Q3DEFORM_TEXT2:
8241                 case Q3DEFORM_TEXT3:
8242                 case Q3DEFORM_TEXT4:
8243                 case Q3DEFORM_TEXT5:
8244                 case Q3DEFORM_TEXT6:
8245                 case Q3DEFORM_TEXT7:
8246                 case Q3DEFORM_NONE:
8247                         break;
8248                 case Q3DEFORM_AUTOSPRITE:
8249                         dynamicvertex = true;
8250                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8251                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8252                         break;
8253                 case Q3DEFORM_AUTOSPRITE2:
8254                         dynamicvertex = true;
8255                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8256                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8257                         break;
8258                 case Q3DEFORM_NORMAL:
8259                         dynamicvertex = true;
8260                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8261                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8262                         break;
8263                 case Q3DEFORM_WAVE:
8264                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8265                                 break; // if wavefunc is a nop, ignore this transform
8266                         dynamicvertex = true;
8267                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8268                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8269                         break;
8270                 case Q3DEFORM_BULGE:
8271                         dynamicvertex = true;
8272                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8273                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8274                         break;
8275                 case Q3DEFORM_MOVE:
8276                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8277                                 break; // if wavefunc is a nop, ignore this transform
8278                         dynamicvertex = true;
8279                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8280                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8281                         break;
8282                 }
8283         }
8284         switch(rsurface.texture->tcgen.tcgen)
8285         {
8286         default:
8287         case Q3TCGEN_TEXTURE:
8288                 break;
8289         case Q3TCGEN_LIGHTMAP:
8290                 dynamicvertex = true;
8291                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8292                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8293                 break;
8294         case Q3TCGEN_VECTOR:
8295                 dynamicvertex = true;
8296                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8297                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8298                 break;
8299         case Q3TCGEN_ENVIRONMENT:
8300                 dynamicvertex = true;
8301                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8302                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8303                 break;
8304         }
8305         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8306         {
8307                 dynamicvertex = true;
8308                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8309                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8310         }
8311
8312         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8313         {
8314                 dynamicvertex = true;
8315                 batchneed |= BATCHNEED_NOGAPS;
8316                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8317         }
8318
8319         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8320         {
8321                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8322                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8323                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8324                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8325                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8326                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8327                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8328         }
8329
8330         // when the model data has no vertex buffer (dynamic mesh), we need to
8331         // eliminate gaps
8332         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8333                 batchneed |= BATCHNEED_NOGAPS;
8334
8335         // if needsupdate, we have to do a dynamic vertex batch for sure
8336         if (needsupdate & batchneed)
8337                 dynamicvertex = true;
8338
8339         // see if we need to build vertexmesh from arrays
8340         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8341                 dynamicvertex = true;
8342
8343         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8344         // also some drivers strongly dislike firstvertex
8345         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8346                 dynamicvertex = true;
8347
8348         rsurface.batchvertex3f = rsurface.modelvertex3f;
8349         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8350         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8351         rsurface.batchsvector3f = rsurface.modelsvector3f;
8352         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8353         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8354         rsurface.batchtvector3f = rsurface.modeltvector3f;
8355         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8356         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8357         rsurface.batchnormal3f = rsurface.modelnormal3f;
8358         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8359         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8360         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8361         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8362         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8363         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8364         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8365         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8366         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8367         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8368         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8369         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8370         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8371         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8372         rsurface.batchelement3i = rsurface.modelelement3i;
8373         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8374         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8375         rsurface.batchelement3s = rsurface.modelelement3s;
8376         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8377         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8378
8379         // if any dynamic vertex processing has to occur in software, we copy the
8380         // entire surface list together before processing to rebase the vertices
8381         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8382         //
8383         // if any gaps exist and we do not have a static vertex buffer, we have to
8384         // copy the surface list together to avoid wasting upload bandwidth on the
8385         // vertices in the gaps.
8386         //
8387         // if gaps exist and we have a static vertex buffer, we still have to
8388         // combine the index buffer ranges into one dynamic index buffer.
8389         //
8390         // in all cases we end up with data that can be drawn in one call.
8391
8392         if (!dynamicvertex)
8393         {
8394                 // static vertex data, just set pointers...
8395                 rsurface.batchgeneratedvertex = false;
8396                 // if there are gaps, we want to build a combined index buffer,
8397                 // otherwise use the original static buffer with an appropriate offset
8398                 if (gaps)
8399                 {
8400                         // build a new triangle elements array for this batch
8401                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8402                         rsurface.batchfirsttriangle = 0;
8403                         numtriangles = 0;
8404                         for (i = 0;i < texturenumsurfaces;i++)
8405                         {
8406                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8407                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8408                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8409                                 numtriangles += surfacenumtriangles;
8410                         }
8411                         rsurface.batchelement3i_indexbuffer = NULL;
8412                         rsurface.batchelement3i_bufferoffset = 0;
8413                         rsurface.batchelement3s = NULL;
8414                         rsurface.batchelement3s_indexbuffer = NULL;
8415                         rsurface.batchelement3s_bufferoffset = 0;
8416                         if (endvertex <= 65536)
8417                         {
8418                                 // make a 16bit (unsigned short) index array if possible
8419                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8420                                 for (i = 0;i < numtriangles*3;i++)
8421                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8422                         }
8423                 }
8424                 return;
8425         }
8426
8427         // something needs software processing, do it for real...
8428         // we only directly handle separate array data in this case and then
8429         // generate interleaved data if needed...
8430         rsurface.batchgeneratedvertex = true;
8431
8432         // now copy the vertex data into a combined array and make an index array
8433         // (this is what Quake3 does all the time)
8434         //if (gaps || rsurface.batchfirstvertex)
8435         {
8436                 rsurface.batchvertex3fbuffer = NULL;
8437                 rsurface.batchvertexmesh = NULL;
8438                 rsurface.batchvertexmeshbuffer = NULL;
8439                 rsurface.batchvertex3f = NULL;
8440                 rsurface.batchvertex3f_vertexbuffer = NULL;
8441                 rsurface.batchvertex3f_bufferoffset = 0;
8442                 rsurface.batchsvector3f = NULL;
8443                 rsurface.batchsvector3f_vertexbuffer = NULL;
8444                 rsurface.batchsvector3f_bufferoffset = 0;
8445                 rsurface.batchtvector3f = NULL;
8446                 rsurface.batchtvector3f_vertexbuffer = NULL;
8447                 rsurface.batchtvector3f_bufferoffset = 0;
8448                 rsurface.batchnormal3f = NULL;
8449                 rsurface.batchnormal3f_vertexbuffer = NULL;
8450                 rsurface.batchnormal3f_bufferoffset = 0;
8451                 rsurface.batchlightmapcolor4f = NULL;
8452                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8453                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8454                 rsurface.batchtexcoordtexture2f = NULL;
8455                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8456                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8457                 rsurface.batchtexcoordlightmap2f = NULL;
8458                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8459                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8460                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8461                 rsurface.batchelement3i_indexbuffer = NULL;
8462                 rsurface.batchelement3i_bufferoffset = 0;
8463                 rsurface.batchelement3s = NULL;
8464                 rsurface.batchelement3s_indexbuffer = NULL;
8465                 rsurface.batchelement3s_bufferoffset = 0;
8466                 // we'll only be setting up certain arrays as needed
8467                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8468                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8469                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8470                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8471                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8472                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8473                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8474                 {
8475                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8476                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8477                 }
8478                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8479                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8480                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8481                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8482                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8483                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8484                 numvertices = 0;
8485                 numtriangles = 0;
8486                 for (i = 0;i < texturenumsurfaces;i++)
8487                 {
8488                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8489                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8490                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8491                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8492                         // copy only the data requested
8493                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8494                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8495                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8496                         {
8497                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8498                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8499                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8500                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8501                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8502                                 {
8503                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8504                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8505                                 }
8506                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8507                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8508                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8509                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8510                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8511                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8512                         }
8513                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8514                         numvertices += surfacenumvertices;
8515                         numtriangles += surfacenumtriangles;
8516                 }
8517
8518                 // generate a 16bit index array as well if possible
8519                 // (in general, dynamic batches fit)
8520                 if (numvertices <= 65536)
8521                 {
8522                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8523                         for (i = 0;i < numtriangles*3;i++)
8524                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8525                 }
8526
8527                 // since we've copied everything, the batch now starts at 0
8528                 rsurface.batchfirstvertex = 0;
8529                 rsurface.batchnumvertices = batchnumvertices;
8530                 rsurface.batchfirsttriangle = 0;
8531                 rsurface.batchnumtriangles = batchnumtriangles;
8532         }
8533
8534         // q1bsp surfaces rendered in vertex color mode have to have colors
8535         // calculated based on lightstyles
8536         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8537         {
8538                 // generate color arrays for the surfaces in this list
8539                 int c[4];
8540                 int scale;
8541                 int size3;
8542                 const int *offsets;
8543                 const unsigned char *lm;
8544                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8545                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8546                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8547                 numvertices = 0;
8548                 for (i = 0;i < texturenumsurfaces;i++)
8549                 {
8550                         surface = texturesurfacelist[i];
8551                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8552                         surfacenumvertices = surface->num_vertices;
8553                         if (surface->lightmapinfo->samples)
8554                         {
8555                                 for (j = 0;j < surfacenumvertices;j++)
8556                                 {
8557                                         lm = surface->lightmapinfo->samples + offsets[j];
8558                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8559                                         VectorScale(lm, scale, c);
8560                                         if (surface->lightmapinfo->styles[1] != 255)
8561                                         {
8562                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8563                                                 lm += size3;
8564                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8565                                                 VectorMA(c, scale, lm, c);
8566                                                 if (surface->lightmapinfo->styles[2] != 255)
8567                                                 {
8568                                                         lm += size3;
8569                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8570                                                         VectorMA(c, scale, lm, c);
8571                                                         if (surface->lightmapinfo->styles[3] != 255)
8572                                                         {
8573                                                                 lm += size3;
8574                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8575                                                                 VectorMA(c, scale, lm, c);
8576                                                         }
8577                                                 }
8578                                         }
8579                                         c[0] >>= 7;
8580                                         c[1] >>= 7;
8581                                         c[2] >>= 7;
8582                                         Vector4Set(rsurface.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);
8583                                         numvertices++;
8584                                 }
8585                         }
8586                         else
8587                         {
8588                                 for (j = 0;j < surfacenumvertices;j++)
8589                                 {
8590                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8591                                         numvertices++;
8592                                 }
8593                         }
8594                 }
8595         }
8596
8597         // if vertices are deformed (sprite flares and things in maps, possibly
8598         // water waves, bulges and other deformations), modify the copied vertices
8599         // in place
8600         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8601         {
8602                 switch (deform->deform)
8603                 {
8604                 default:
8605                 case Q3DEFORM_PROJECTIONSHADOW:
8606                 case Q3DEFORM_TEXT0:
8607                 case Q3DEFORM_TEXT1:
8608                 case Q3DEFORM_TEXT2:
8609                 case Q3DEFORM_TEXT3:
8610                 case Q3DEFORM_TEXT4:
8611                 case Q3DEFORM_TEXT5:
8612                 case Q3DEFORM_TEXT6:
8613                 case Q3DEFORM_TEXT7:
8614                 case Q3DEFORM_NONE:
8615                         break;
8616                 case Q3DEFORM_AUTOSPRITE:
8617                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8618                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8619                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8620                         VectorNormalize(newforward);
8621                         VectorNormalize(newright);
8622                         VectorNormalize(newup);
8623 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8624 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8625 //                      rsurface.batchvertex3f_bufferoffset = 0;
8626 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8627 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8628 //                      rsurface.batchsvector3f_bufferoffset = 0;
8629 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8630 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8631 //                      rsurface.batchtvector3f_bufferoffset = 0;
8632 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8633 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8634 //                      rsurface.batchnormal3f_bufferoffset = 0;
8635                         // a single autosprite surface can contain multiple sprites...
8636                         for (j = 0;j < batchnumvertices - 3;j += 4)
8637                         {
8638                                 VectorClear(center);
8639                                 for (i = 0;i < 4;i++)
8640                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8641                                 VectorScale(center, 0.25f, center);
8642                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8643                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8644                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8645                                 for (i = 0;i < 4;i++)
8646                                 {
8647                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8648                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8649                                 }
8650                         }
8651                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8652                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8653                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8654                         break;
8655                 case Q3DEFORM_AUTOSPRITE2:
8656                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8657                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8658                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8659                         VectorNormalize(newforward);
8660                         VectorNormalize(newright);
8661                         VectorNormalize(newup);
8662 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8663 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8664 //                      rsurface.batchvertex3f_bufferoffset = 0;
8665                         {
8666                                 const float *v1, *v2;
8667                                 vec3_t start, end;
8668                                 float f, l;
8669                                 struct
8670                                 {
8671                                         float length2;
8672                                         const float *v1;
8673                                         const float *v2;
8674                                 }
8675                                 shortest[2];
8676                                 memset(shortest, 0, sizeof(shortest));
8677                                 // a single autosprite surface can contain multiple sprites...
8678                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8679                                 {
8680                                         VectorClear(center);
8681                                         for (i = 0;i < 4;i++)
8682                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8683                                         VectorScale(center, 0.25f, center);
8684                                         // find the two shortest edges, then use them to define the
8685                                         // axis vectors for rotating around the central axis
8686                                         for (i = 0;i < 6;i++)
8687                                         {
8688                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8689                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8690                                                 l = VectorDistance2(v1, v2);
8691                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8692                                                 if (v1[2] != v2[2])
8693                                                         l += (1.0f / 1024.0f);
8694                                                 if (shortest[0].length2 > l || i == 0)
8695                                                 {
8696                                                         shortest[1] = shortest[0];
8697                                                         shortest[0].length2 = l;
8698                                                         shortest[0].v1 = v1;
8699                                                         shortest[0].v2 = v2;
8700                                                 }
8701                                                 else if (shortest[1].length2 > l || i == 1)
8702                                                 {
8703                                                         shortest[1].length2 = l;
8704                                                         shortest[1].v1 = v1;
8705                                                         shortest[1].v2 = v2;
8706                                                 }
8707                                         }
8708                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8709                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8710                                         // this calculates the right vector from the shortest edge
8711                                         // and the up vector from the edge midpoints
8712                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8713                                         VectorNormalize(right);
8714                                         VectorSubtract(end, start, up);
8715                                         VectorNormalize(up);
8716                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8717                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8718                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8719                                         VectorNegate(forward, forward);
8720                                         VectorReflect(forward, 0, up, forward);
8721                                         VectorNormalize(forward);
8722                                         CrossProduct(up, forward, newright);
8723                                         VectorNormalize(newright);
8724                                         // rotate the quad around the up axis vector, this is made
8725                                         // especially easy by the fact we know the quad is flat,
8726                                         // so we only have to subtract the center position and
8727                                         // measure distance along the right vector, and then
8728                                         // multiply that by the newright vector and add back the
8729                                         // center position
8730                                         // we also need to subtract the old position to undo the
8731                                         // displacement from the center, which we do with a
8732                                         // DotProduct, the subtraction/addition of center is also
8733                                         // optimized into DotProducts here
8734                                         l = DotProduct(right, center);
8735                                         for (i = 0;i < 4;i++)
8736                                         {
8737                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8738                                                 f = DotProduct(right, v1) - l;
8739                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8740                                         }
8741                                 }
8742                         }
8743                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8744                         {
8745 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8746 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8747 //                              rsurface.batchnormal3f_bufferoffset = 0;
8748                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8749                         }
8750                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8751                         {
8752 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8753 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8754 //                              rsurface.batchsvector3f_bufferoffset = 0;
8755 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8756 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8757 //                              rsurface.batchtvector3f_bufferoffset = 0;
8758                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8759                         }
8760                         break;
8761                 case Q3DEFORM_NORMAL:
8762                         // deform the normals to make reflections wavey
8763                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8764                         rsurface.batchnormal3f_vertexbuffer = NULL;
8765                         rsurface.batchnormal3f_bufferoffset = 0;
8766                         for (j = 0;j < batchnumvertices;j++)
8767                         {
8768                                 float vertex[3];
8769                                 float *normal = rsurface.batchnormal3f + 3*j;
8770                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8771                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8772                                 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]);
8773                                 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]);
8774                                 VectorNormalize(normal);
8775                         }
8776                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8777                         {
8778 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8779 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8780 //                              rsurface.batchsvector3f_bufferoffset = 0;
8781 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8782 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8783 //                              rsurface.batchtvector3f_bufferoffset = 0;
8784                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8785                         }
8786                         break;
8787                 case Q3DEFORM_WAVE:
8788                         // deform vertex array to make wavey water and flags and such
8789                         waveparms[0] = deform->waveparms[0];
8790                         waveparms[1] = deform->waveparms[1];
8791                         waveparms[2] = deform->waveparms[2];
8792                         waveparms[3] = deform->waveparms[3];
8793                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8794                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8795                         // this is how a divisor of vertex influence on deformation
8796                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8797                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8798 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8799 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8800 //                      rsurface.batchvertex3f_bufferoffset = 0;
8801 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8802 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8803 //                      rsurface.batchnormal3f_bufferoffset = 0;
8804                         for (j = 0;j < batchnumvertices;j++)
8805                         {
8806                                 // if the wavefunc depends on time, evaluate it per-vertex
8807                                 if (waveparms[3])
8808                                 {
8809                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8810                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8811                                 }
8812                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8813                         }
8814                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8815                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8816                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8817                         {
8818 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8819 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8820 //                              rsurface.batchsvector3f_bufferoffset = 0;
8821 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8822 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8823 //                              rsurface.batchtvector3f_bufferoffset = 0;
8824                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8825                         }
8826                         break;
8827                 case Q3DEFORM_BULGE:
8828                         // deform vertex array to make the surface have moving bulges
8829 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8830 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8831 //                      rsurface.batchvertex3f_bufferoffset = 0;
8832 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8833 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8834 //                      rsurface.batchnormal3f_bufferoffset = 0;
8835                         for (j = 0;j < batchnumvertices;j++)
8836                         {
8837                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8838                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8839                         }
8840                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8841                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8842                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8843                         {
8844 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8845 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8846 //                              rsurface.batchsvector3f_bufferoffset = 0;
8847 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8848 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8849 //                              rsurface.batchtvector3f_bufferoffset = 0;
8850                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8851                         }
8852                         break;
8853                 case Q3DEFORM_MOVE:
8854                         // deform vertex array
8855                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8856                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8857                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8858                         VectorScale(deform->parms, scale, waveparms);
8859 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8860 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8861 //                      rsurface.batchvertex3f_bufferoffset = 0;
8862                         for (j = 0;j < batchnumvertices;j++)
8863                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8864                         break;
8865                 }
8866         }
8867
8868         // generate texcoords based on the chosen texcoord source
8869         switch(rsurface.texture->tcgen.tcgen)
8870         {
8871         default:
8872         case Q3TCGEN_TEXTURE:
8873                 break;
8874         case Q3TCGEN_LIGHTMAP:
8875 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8876 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8877 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8878                 if (rsurface.batchtexcoordlightmap2f)
8879                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8880                 break;
8881         case Q3TCGEN_VECTOR:
8882 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8883 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8884 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8885                 for (j = 0;j < batchnumvertices;j++)
8886                 {
8887                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8888                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8889                 }
8890                 break;
8891         case Q3TCGEN_ENVIRONMENT:
8892                 // make environment reflections using a spheremap
8893                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8894                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8895                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8896                 for (j = 0;j < batchnumvertices;j++)
8897                 {
8898                         // identical to Q3A's method, but executed in worldspace so
8899                         // carried models can be shiny too
8900
8901                         float viewer[3], d, reflected[3], worldreflected[3];
8902
8903                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8904                         // VectorNormalize(viewer);
8905
8906                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8907
8908                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8909                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8910                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8911                         // note: this is proportinal to viewer, so we can normalize later
8912
8913                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8914                         VectorNormalize(worldreflected);
8915
8916                         // note: this sphere map only uses world x and z!
8917                         // so positive and negative y will LOOK THE SAME.
8918                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8919                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8920                 }
8921                 break;
8922         }
8923         // the only tcmod that needs software vertex processing is turbulent, so
8924         // check for it here and apply the changes if needed
8925         // and we only support that as the first one
8926         // (handling a mixture of turbulent and other tcmods would be problematic
8927         //  without punting it entirely to a software path)
8928         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8929         {
8930                 amplitude = rsurface.texture->tcmods[0].parms[1];
8931                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8932 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8933 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8934 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8935                 for (j = 0;j < batchnumvertices;j++)
8936                 {
8937                         rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8938                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8939                 }
8940         }
8941
8942         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8943         {
8944                 // convert the modified arrays to vertex structs
8945 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8946 //              rsurface.batchvertexmeshbuffer = NULL;
8947                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8948                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8949                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8950                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8951                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8952                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8953                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8954                 {
8955                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8956                         {
8957                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8958                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8959                         }
8960                 }
8961                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8962                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8963                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8964                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8965                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8966                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8967                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8968                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8970         }
8971 }
8972
8973 void RSurf_DrawBatch(void)
8974 {
8975         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8976         // through the pipeline, killing it earlier in the pipeline would have
8977         // per-surface overhead rather than per-batch overhead, so it's best to
8978         // reject it here, before it hits glDraw.
8979         if (rsurface.batchnumtriangles == 0)
8980                 return;
8981 #if 0
8982         // batch debugging code
8983         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8984         {
8985                 int i;
8986                 int j;
8987                 int c;
8988                 const int *e;
8989                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8990                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8991                 {
8992                         c = e[i];
8993                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8994                         {
8995                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8996                                 {
8997                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8998                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
8999                                         break;
9000                                 }
9001                         }
9002                 }
9003         }
9004 #endif
9005         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);
9006 }
9007
9008 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9009 {
9010         // pick the closest matching water plane
9011         int planeindex, vertexindex, bestplaneindex = -1;
9012         float d, bestd;
9013         vec3_t vert;
9014         const float *v;
9015         r_waterstate_waterplane_t *p;
9016         qboolean prepared = false;
9017         bestd = 0;
9018         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9019         {
9020                 if(p->camera_entity != rsurface.texture->camera_entity)
9021                         continue;
9022                 d = 0;
9023                 if(!prepared)
9024                 {
9025                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9026                         prepared = true;
9027                         if(rsurface.batchnumvertices == 0)
9028                                 break;
9029                 }
9030                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9031                 {
9032                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9033                         d += fabs(PlaneDiff(vert, &p->plane));
9034                 }
9035                 if (bestd > d || bestplaneindex < 0)
9036                 {
9037                         bestd = d;
9038                         bestplaneindex = planeindex;
9039                 }
9040         }
9041         return bestplaneindex;
9042         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9043         // this situation though, as it might be better to render single larger
9044         // batches with useless stuff (backface culled for example) than to
9045         // render multiple smaller batches
9046 }
9047
9048 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9049 {
9050         int i;
9051         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9052         rsurface.passcolor4f_vertexbuffer = 0;
9053         rsurface.passcolor4f_bufferoffset = 0;
9054         for (i = 0;i < rsurface.batchnumvertices;i++)
9055                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9056 }
9057
9058 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9059 {
9060         int i;
9061         float f;
9062         const float *v;
9063         const float *c;
9064         float *c2;
9065         if (rsurface.passcolor4f)
9066         {
9067                 // generate color arrays
9068                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9069                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9070                 rsurface.passcolor4f_vertexbuffer = 0;
9071                 rsurface.passcolor4f_bufferoffset = 0;
9072                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9073                 {
9074                         f = RSurf_FogVertex(v);
9075                         c2[0] = c[0] * f;
9076                         c2[1] = c[1] * f;
9077                         c2[2] = c[2] * f;
9078                         c2[3] = c[3];
9079                 }
9080         }
9081         else
9082         {
9083                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9084                 rsurface.passcolor4f_vertexbuffer = 0;
9085                 rsurface.passcolor4f_bufferoffset = 0;
9086                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9087                 {
9088                         f = RSurf_FogVertex(v);
9089                         c2[0] = f;
9090                         c2[1] = f;
9091                         c2[2] = f;
9092                         c2[3] = 1;
9093                 }
9094         }
9095 }
9096
9097 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9098 {
9099         int i;
9100         float f;
9101         const float *v;
9102         const float *c;
9103         float *c2;
9104         if (!rsurface.passcolor4f)
9105                 return;
9106         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9107         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9108         rsurface.passcolor4f_vertexbuffer = 0;
9109         rsurface.passcolor4f_bufferoffset = 0;
9110         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9111         {
9112                 f = RSurf_FogVertex(v);
9113                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9114                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9115                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9116                 c2[3] = c[3];
9117         }
9118 }
9119
9120 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9121 {
9122         int i;
9123         const float *c;
9124         float *c2;
9125         if (!rsurface.passcolor4f)
9126                 return;
9127         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9128         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9129         rsurface.passcolor4f_vertexbuffer = 0;
9130         rsurface.passcolor4f_bufferoffset = 0;
9131         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9132         {
9133                 c2[0] = c[0] * r;
9134                 c2[1] = c[1] * g;
9135                 c2[2] = c[2] * b;
9136                 c2[3] = c[3] * a;
9137         }
9138 }
9139
9140 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9141 {
9142         int i;
9143         const float *c;
9144         float *c2;
9145         if (!rsurface.passcolor4f)
9146                 return;
9147         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9148         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149         rsurface.passcolor4f_vertexbuffer = 0;
9150         rsurface.passcolor4f_bufferoffset = 0;
9151         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9152         {
9153                 c2[0] = c[0] + r_refdef.scene.ambient;
9154                 c2[1] = c[1] + r_refdef.scene.ambient;
9155                 c2[2] = c[2] + r_refdef.scene.ambient;
9156                 c2[3] = c[3];
9157         }
9158 }
9159
9160 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9161 {
9162         // TODO: optimize
9163         rsurface.passcolor4f = NULL;
9164         rsurface.passcolor4f_vertexbuffer = 0;
9165         rsurface.passcolor4f_bufferoffset = 0;
9166         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9167         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9168         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9169         GL_Color(r, g, b, a);
9170         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9171         RSurf_DrawBatch();
9172 }
9173
9174 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9175 {
9176         // TODO: optimize applyfog && applycolor case
9177         // just apply fog if necessary, and tint the fog color array if necessary
9178         rsurface.passcolor4f = NULL;
9179         rsurface.passcolor4f_vertexbuffer = 0;
9180         rsurface.passcolor4f_bufferoffset = 0;
9181         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9182         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9183         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9184         GL_Color(r, g, b, a);
9185         RSurf_DrawBatch();
9186 }
9187
9188 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9189 {
9190         // TODO: optimize
9191         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9192         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9193         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9194         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9195         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9196         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9197         GL_Color(r, g, b, a);
9198         RSurf_DrawBatch();
9199 }
9200
9201 static void RSurf_DrawBatch_GL11_ClampColor(void)
9202 {
9203         int i;
9204         const float *c1;
9205         float *c2;
9206         if (!rsurface.passcolor4f)
9207                 return;
9208         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9209         {
9210                 c2[0] = bound(0.0f, c1[0], 1.0f);
9211                 c2[1] = bound(0.0f, c1[1], 1.0f);
9212                 c2[2] = bound(0.0f, c1[2], 1.0f);
9213                 c2[3] = bound(0.0f, c1[3], 1.0f);
9214         }
9215 }
9216
9217 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9218 {
9219         int i;
9220         float f;
9221         const float *v;
9222         const float *n;
9223         float *c;
9224         //vec3_t eyedir;
9225
9226         // fake shading
9227         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9228         rsurface.passcolor4f_vertexbuffer = 0;
9229         rsurface.passcolor4f_bufferoffset = 0;
9230         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9231         {
9232                 f = -DotProduct(r_refdef.view.forward, n);
9233                 f = max(0, f);
9234                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9235                 f *= r_refdef.lightmapintensity;
9236                 Vector4Set(c, f, f, f, 1);
9237         }
9238 }
9239
9240 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9241 {
9242         RSurf_DrawBatch_GL11_ApplyFakeLight();
9243         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9244         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9245         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9246         GL_Color(r, g, b, a);
9247         RSurf_DrawBatch();
9248 }
9249
9250 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9251 {
9252         int i;
9253         float f;
9254         float alpha;
9255         const float *v;
9256         const float *n;
9257         float *c;
9258         vec3_t ambientcolor;
9259         vec3_t diffusecolor;
9260         vec3_t lightdir;
9261         // TODO: optimize
9262         // model lighting
9263         VectorCopy(rsurface.modellight_lightdir, lightdir);
9264         f = 0.5f * r_refdef.lightmapintensity;
9265         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9266         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9267         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9268         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9269         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9270         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9271         alpha = *a;
9272         if (VectorLength2(diffusecolor) > 0)
9273         {
9274                 // q3-style directional shading
9275                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276                 rsurface.passcolor4f_vertexbuffer = 0;
9277                 rsurface.passcolor4f_bufferoffset = 0;
9278                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9279                 {
9280                         if ((f = DotProduct(n, lightdir)) > 0)
9281                                 VectorMA(ambientcolor, f, diffusecolor, c);
9282                         else
9283                                 VectorCopy(ambientcolor, c);
9284                         c[3] = alpha;
9285                 }
9286                 *r = 1;
9287                 *g = 1;
9288                 *b = 1;
9289                 *a = 1;
9290                 *applycolor = false;
9291         }
9292         else
9293         {
9294                 *r = ambientcolor[0];
9295                 *g = ambientcolor[1];
9296                 *b = ambientcolor[2];
9297                 rsurface.passcolor4f = NULL;
9298                 rsurface.passcolor4f_vertexbuffer = 0;
9299                 rsurface.passcolor4f_bufferoffset = 0;
9300         }
9301 }
9302
9303 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9304 {
9305         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9306         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9307         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9308         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9309         GL_Color(r, g, b, a);
9310         RSurf_DrawBatch();
9311 }
9312
9313 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9314 {
9315         int i;
9316         float f;
9317         const float *v;
9318         float *c;
9319         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9320         {
9321                 f = 1 - RSurf_FogVertex(v);
9322                 c[0] = r;
9323                 c[1] = g;
9324                 c[2] = b;
9325                 c[3] = f * a;
9326         }
9327 }
9328
9329 void RSurf_SetupDepthAndCulling(void)
9330 {
9331         // submodels are biased to avoid z-fighting with world surfaces that they
9332         // may be exactly overlapping (avoids z-fighting artifacts on certain
9333         // doors and things in Quake maps)
9334         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9335         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9336         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9337         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9338 }
9339
9340 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9341 {
9342         // transparent sky would be ridiculous
9343         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9344                 return;
9345         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9346         skyrenderlater = true;
9347         RSurf_SetupDepthAndCulling();
9348         GL_DepthMask(true);
9349         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9350         // skymasking on them, and Quake3 never did sky masking (unlike
9351         // software Quake and software Quake2), so disable the sky masking
9352         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9353         // and skymasking also looks very bad when noclipping outside the
9354         // level, so don't use it then either.
9355         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9356         {
9357                 R_Mesh_ResetTextureState();
9358                 if (skyrendermasked)
9359                 {
9360                         R_SetupShader_DepthOrShadow();
9361                         // depth-only (masking)
9362                         GL_ColorMask(0,0,0,0);
9363                         // just to make sure that braindead drivers don't draw
9364                         // anything despite that colormask...
9365                         GL_BlendFunc(GL_ZERO, GL_ONE);
9366                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9367                         if (rsurface.batchvertex3fbuffer)
9368                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9369                         else
9370                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9371                 }
9372                 else
9373                 {
9374                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9375                         // fog sky
9376                         GL_BlendFunc(GL_ONE, GL_ZERO);
9377                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9378                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9379                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9380                 }
9381                 RSurf_DrawBatch();
9382                 if (skyrendermasked)
9383                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9384         }
9385         R_Mesh_ResetTextureState();
9386         GL_Color(1, 1, 1, 1);
9387 }
9388
9389 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9390 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9391 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9392 {
9393         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9394                 return;
9395         if (prepass)
9396         {
9397                 // render screenspace normalmap to texture
9398                 GL_DepthMask(true);
9399                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9400                 RSurf_DrawBatch();
9401                 return;
9402         }
9403
9404         // bind lightmap texture
9405
9406         // water/refraction/reflection/camera surfaces have to be handled specially
9407         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9408         {
9409                 int start, end, startplaneindex;
9410                 for (start = 0;start < texturenumsurfaces;start = end)
9411                 {
9412                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9413                         if(startplaneindex < 0)
9414                         {
9415                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9416                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9417                                 end = start + 1;
9418                                 continue;
9419                         }
9420                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9421                                 ;
9422                         // now that we have a batch using the same planeindex, render it
9423                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9424                         {
9425                                 // render water or distortion background
9426                                 GL_DepthMask(true);
9427                                 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));
9428                                 RSurf_DrawBatch();
9429                                 // blend surface on top
9430                                 GL_DepthMask(false);
9431                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9432                                 RSurf_DrawBatch();
9433                         }
9434                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9435                         {
9436                                 // render surface with reflection texture as input
9437                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9438                                 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));
9439                                 RSurf_DrawBatch();
9440                         }
9441                 }
9442                 return;
9443         }
9444
9445         // render surface batch normally
9446         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9447         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9448         RSurf_DrawBatch();
9449 }
9450
9451 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9452 {
9453         // OpenGL 1.3 path - anything not completely ancient
9454         qboolean applycolor;
9455         qboolean applyfog;
9456         int layerindex;
9457         const texturelayer_t *layer;
9458         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);
9459         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9460
9461         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9462         {
9463                 vec4_t layercolor;
9464                 int layertexrgbscale;
9465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9466                 {
9467                         if (layerindex == 0)
9468                                 GL_AlphaTest(true);
9469                         else
9470                         {
9471                                 GL_AlphaTest(false);
9472                                 GL_DepthFunc(GL_EQUAL);
9473                         }
9474                 }
9475                 GL_DepthMask(layer->depthmask && writedepth);
9476                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9477                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9478                 {
9479                         layertexrgbscale = 4;
9480                         VectorScale(layer->color, 0.25f, layercolor);
9481                 }
9482                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9483                 {
9484                         layertexrgbscale = 2;
9485                         VectorScale(layer->color, 0.5f, layercolor);
9486                 }
9487                 else
9488                 {
9489                         layertexrgbscale = 1;
9490                         VectorScale(layer->color, 1.0f, layercolor);
9491                 }
9492                 layercolor[3] = layer->color[3];
9493                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9494                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9495                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9496                 switch (layer->type)
9497                 {
9498                 case TEXTURELAYERTYPE_LITTEXTURE:
9499                         // single-pass lightmapped texture with 2x rgbscale
9500                         R_Mesh_TexBind(0, r_texture_white);
9501                         R_Mesh_TexMatrix(0, NULL);
9502                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9503                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9504                         R_Mesh_TexBind(1, layer->texture);
9505                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9506                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9507                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9508                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9509                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9510                         else if (FAKELIGHT_ENABLED)
9511                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9512                         else if (rsurface.uselightmaptexture)
9513                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9514                         else
9515                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9516                         break;
9517                 case TEXTURELAYERTYPE_TEXTURE:
9518                         // singletexture unlit texture with transparency support
9519                         R_Mesh_TexBind(0, layer->texture);
9520                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9521                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9522                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9523                         R_Mesh_TexBind(1, 0);
9524                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9525                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9526                         break;
9527                 case TEXTURELAYERTYPE_FOG:
9528                         // singletexture fogging
9529                         if (layer->texture)
9530                         {
9531                                 R_Mesh_TexBind(0, layer->texture);
9532                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9533                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9534                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9535                         }
9536                         else
9537                         {
9538                                 R_Mesh_TexBind(0, 0);
9539                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9540                         }
9541                         R_Mesh_TexBind(1, 0);
9542                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9543                         // generate a color array for the fog pass
9544                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9545                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9546                         RSurf_DrawBatch();
9547                         break;
9548                 default:
9549                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9550                 }
9551         }
9552         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9553         {
9554                 GL_DepthFunc(GL_LEQUAL);
9555                 GL_AlphaTest(false);
9556         }
9557 }
9558
9559 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9560 {
9561         // OpenGL 1.1 - crusty old voodoo path
9562         qboolean applyfog;
9563         int layerindex;
9564         const texturelayer_t *layer;
9565         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);
9566         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9567
9568         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9569         {
9570                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9571                 {
9572                         if (layerindex == 0)
9573                                 GL_AlphaTest(true);
9574                         else
9575                         {
9576                                 GL_AlphaTest(false);
9577                                 GL_DepthFunc(GL_EQUAL);
9578                         }
9579                 }
9580                 GL_DepthMask(layer->depthmask && writedepth);
9581                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9582                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9583                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9584                 switch (layer->type)
9585                 {
9586                 case TEXTURELAYERTYPE_LITTEXTURE:
9587                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9588                         {
9589                                 // two-pass lit texture with 2x rgbscale
9590                                 // first the lightmap pass
9591                                 R_Mesh_TexBind(0, r_texture_white);
9592                                 R_Mesh_TexMatrix(0, NULL);
9593                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9594                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9595                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9596                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9597                                 else if (FAKELIGHT_ENABLED)
9598                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9599                                 else if (rsurface.uselightmaptexture)
9600                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9601                                 else
9602                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9603                                 // then apply the texture to it
9604                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9605                                 R_Mesh_TexBind(0, layer->texture);
9606                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9607                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9608                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9609                                 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);
9610                         }
9611                         else
9612                         {
9613                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9614                                 R_Mesh_TexBind(0, layer->texture);
9615                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9616                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9617                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9618                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9619                                         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);
9620                                 else
9621                                         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);
9622                         }
9623                         break;
9624                 case TEXTURELAYERTYPE_TEXTURE:
9625                         // singletexture unlit texture with transparency support
9626                         R_Mesh_TexBind(0, layer->texture);
9627                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9628                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9629                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9630                         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);
9631                         break;
9632                 case TEXTURELAYERTYPE_FOG:
9633                         // singletexture fogging
9634                         if (layer->texture)
9635                         {
9636                                 R_Mesh_TexBind(0, layer->texture);
9637                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9638                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9639                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9640                         }
9641                         else
9642                         {
9643                                 R_Mesh_TexBind(0, 0);
9644                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9645                         }
9646                         // generate a color array for the fog pass
9647                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9648                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9649                         RSurf_DrawBatch();
9650                         break;
9651                 default:
9652                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9653                 }
9654         }
9655         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9656         {
9657                 GL_DepthFunc(GL_LEQUAL);
9658                 GL_AlphaTest(false);
9659         }
9660 }
9661
9662 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9663 {
9664         int vi;
9665         int j;
9666         r_vertexgeneric_t *batchvertex;
9667         float c[4];
9668
9669 //      R_Mesh_ResetTextureState();
9670         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9671
9672         if(rsurface.texture && rsurface.texture->currentskinframe)
9673         {
9674                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9675                 c[3] *= rsurface.texture->currentalpha;
9676         }
9677         else
9678         {
9679                 c[0] = 1;
9680                 c[1] = 0;
9681                 c[2] = 1;
9682                 c[3] = 1;
9683         }
9684
9685         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9686         {
9687                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9688                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9689                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9690         }
9691
9692         // brighten it up (as texture value 127 means "unlit")
9693         c[0] *= 2 * r_refdef.view.colorscale;
9694         c[1] *= 2 * r_refdef.view.colorscale;
9695         c[2] *= 2 * r_refdef.view.colorscale;
9696
9697         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9698                 c[3] *= r_wateralpha.value;
9699
9700         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9701         {
9702                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9703                 GL_DepthMask(false);
9704         }
9705         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9706         {
9707                 GL_BlendFunc(GL_ONE, GL_ONE);
9708                 GL_DepthMask(false);
9709         }
9710         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9711         {
9712                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9713                 GL_DepthMask(false);
9714         }
9715         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9716         {
9717                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9718                 GL_DepthMask(false);
9719         }
9720         else
9721         {
9722                 GL_BlendFunc(GL_ONE, GL_ZERO);
9723                 GL_DepthMask(writedepth);
9724         }
9725
9726         if (r_showsurfaces.integer == 3)
9727         {
9728                 rsurface.passcolor4f = NULL;
9729
9730                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9731                 {
9732                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9733
9734                         rsurface.passcolor4f = NULL;
9735                         rsurface.passcolor4f_vertexbuffer = 0;
9736                         rsurface.passcolor4f_bufferoffset = 0;
9737                 }
9738                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9739                 {
9740                         qboolean applycolor = true;
9741                         float one = 1.0;
9742
9743                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9744
9745                         r_refdef.lightmapintensity = 1;
9746                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9747                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9748                 }
9749                 else if (FAKELIGHT_ENABLED)
9750                 {
9751                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9752
9753                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9754                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9755                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9756                 }
9757                 else
9758                 {
9759                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9760
9761                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9762                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9763                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9764                 }
9765
9766                 if(!rsurface.passcolor4f)
9767                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9768
9769                 RSurf_DrawBatch_GL11_ApplyAmbient();
9770                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9771                 if(r_refdef.fogenabled)
9772                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9773                 RSurf_DrawBatch_GL11_ClampColor();
9774
9775                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9776                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9777                 RSurf_DrawBatch();
9778         }
9779         else if (!r_refdef.view.showdebug)
9780         {
9781                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9782                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9783                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9784                 {
9785                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9786                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9787                 }
9788                 R_Mesh_PrepareVertices_Generic_Unlock();
9789                 RSurf_DrawBatch();
9790         }
9791         else if (r_showsurfaces.integer == 4)
9792         {
9793                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9794                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9795                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9796                 {
9797                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9798                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9799                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9800                 }
9801                 R_Mesh_PrepareVertices_Generic_Unlock();
9802                 RSurf_DrawBatch();
9803         }
9804         else if (r_showsurfaces.integer == 2)
9805         {
9806                 const int *e;
9807                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9809                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9810                 {
9811                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9812                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9813                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9814                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9815                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9816                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9817                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9818                 }
9819                 R_Mesh_PrepareVertices_Generic_Unlock();
9820                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9821         }
9822         else
9823         {
9824                 int texturesurfaceindex;
9825                 int k;
9826                 const msurface_t *surface;
9827                 float surfacecolor4f[4];
9828                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9829                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9830                 vi = 0;
9831                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9832                 {
9833                         surface = texturesurfacelist[texturesurfaceindex];
9834                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9835                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9836                         for (j = 0;j < surface->num_vertices;j++)
9837                         {
9838                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9839                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9840                                 vi++;
9841                         }
9842                 }
9843                 R_Mesh_PrepareVertices_Generic_Unlock();
9844                 RSurf_DrawBatch();
9845         }
9846 }
9847
9848 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9849 {
9850         CHECKGLERROR
9851         RSurf_SetupDepthAndCulling();
9852         if (r_showsurfaces.integer)
9853         {
9854                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9855                 return;
9856         }
9857         switch (vid.renderpath)
9858         {
9859         case RENDERPATH_GL20:
9860         case RENDERPATH_D3D9:
9861         case RENDERPATH_D3D10:
9862         case RENDERPATH_D3D11:
9863         case RENDERPATH_SOFT:
9864         case RENDERPATH_GLES2:
9865                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9866                 break;
9867         case RENDERPATH_GL13:
9868                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9869                 break;
9870         case RENDERPATH_GL11:
9871                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9872                 break;
9873         }
9874         CHECKGLERROR
9875 }
9876
9877 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9878 {
9879         CHECKGLERROR
9880         RSurf_SetupDepthAndCulling();
9881         if (r_showsurfaces.integer)
9882         {
9883                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9884                 return;
9885         }
9886         switch (vid.renderpath)
9887         {
9888         case RENDERPATH_GL20:
9889         case RENDERPATH_D3D9:
9890         case RENDERPATH_D3D10:
9891         case RENDERPATH_D3D11:
9892         case RENDERPATH_SOFT:
9893         case RENDERPATH_GLES2:
9894                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9895                 break;
9896         case RENDERPATH_GL13:
9897                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9898                 break;
9899         case RENDERPATH_GL11:
9900                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9901                 break;
9902         }
9903         CHECKGLERROR
9904 }
9905
9906 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9907 {
9908         int i, j;
9909         int texturenumsurfaces, endsurface;
9910         texture_t *texture;
9911         const msurface_t *surface;
9912 #define MAXBATCH_TRANSPARENTSURFACES 256
9913         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9914
9915         // if the model is static it doesn't matter what value we give for
9916         // wantnormals and wanttangents, so this logic uses only rules applicable
9917         // to a model, knowing that they are meaningless otherwise
9918         if (ent == r_refdef.scene.worldentity)
9919                 RSurf_ActiveWorldEntity();
9920         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9921                 RSurf_ActiveModelEntity(ent, false, false, false);
9922         else
9923         {
9924                 switch (vid.renderpath)
9925                 {
9926                 case RENDERPATH_GL20:
9927                 case RENDERPATH_D3D9:
9928                 case RENDERPATH_D3D10:
9929                 case RENDERPATH_D3D11:
9930                 case RENDERPATH_SOFT:
9931                 case RENDERPATH_GLES2:
9932                         RSurf_ActiveModelEntity(ent, true, true, false);
9933                         break;
9934                 case RENDERPATH_GL13:
9935                 case RENDERPATH_GL11:
9936                         RSurf_ActiveModelEntity(ent, true, false, false);
9937                         break;
9938                 }
9939         }
9940
9941         if (r_transparentdepthmasking.integer)
9942         {
9943                 qboolean setup = false;
9944                 for (i = 0;i < numsurfaces;i = j)
9945                 {
9946                         j = i + 1;
9947                         surface = rsurface.modelsurfaces + surfacelist[i];
9948                         texture = surface->texture;
9949                         rsurface.texture = R_GetCurrentTexture(texture);
9950                         rsurface.lightmaptexture = NULL;
9951                         rsurface.deluxemaptexture = NULL;
9952                         rsurface.uselightmaptexture = false;
9953                         // scan ahead until we find a different texture
9954                         endsurface = min(i + 1024, numsurfaces);
9955                         texturenumsurfaces = 0;
9956                         texturesurfacelist[texturenumsurfaces++] = surface;
9957                         for (;j < endsurface;j++)
9958                         {
9959                                 surface = rsurface.modelsurfaces + surfacelist[j];
9960                                 if (texture != surface->texture)
9961                                         break;
9962                                 texturesurfacelist[texturenumsurfaces++] = surface;
9963                         }
9964                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9965                                 continue;
9966                         // render the range of surfaces as depth
9967                         if (!setup)
9968                         {
9969                                 setup = true;
9970                                 GL_ColorMask(0,0,0,0);
9971                                 GL_Color(1,1,1,1);
9972                                 GL_DepthTest(true);
9973                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9974                                 GL_DepthMask(true);
9975 //                              R_Mesh_ResetTextureState();
9976                                 R_SetupShader_DepthOrShadow();
9977                         }
9978                         RSurf_SetupDepthAndCulling();
9979                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9980                         if (rsurface.batchvertex3fbuffer)
9981                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9982                         else
9983                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9984                         RSurf_DrawBatch();
9985                 }
9986                 if (setup)
9987                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9988         }
9989
9990         for (i = 0;i < numsurfaces;i = j)
9991         {
9992                 j = i + 1;
9993                 surface = rsurface.modelsurfaces + surfacelist[i];
9994                 texture = surface->texture;
9995                 rsurface.texture = R_GetCurrentTexture(texture);
9996                 // scan ahead until we find a different texture
9997                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9998                 texturenumsurfaces = 0;
9999                 texturesurfacelist[texturenumsurfaces++] = surface;
10000                 if(FAKELIGHT_ENABLED)
10001                 {
10002                         rsurface.lightmaptexture = NULL;
10003                         rsurface.deluxemaptexture = NULL;
10004                         rsurface.uselightmaptexture = false;
10005                         for (;j < endsurface;j++)
10006                         {
10007                                 surface = rsurface.modelsurfaces + surfacelist[j];
10008                                 if (texture != surface->texture)
10009                                         break;
10010                                 texturesurfacelist[texturenumsurfaces++] = surface;
10011                         }
10012                 }
10013                 else
10014                 {
10015                         rsurface.lightmaptexture = surface->lightmaptexture;
10016                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10017                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10018                         for (;j < endsurface;j++)
10019                         {
10020                                 surface = rsurface.modelsurfaces + surfacelist[j];
10021                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10022                                         break;
10023                                 texturesurfacelist[texturenumsurfaces++] = surface;
10024                         }
10025                 }
10026                 // render the range of surfaces
10027                 if (ent == r_refdef.scene.worldentity)
10028                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10029                 else
10030                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10031         }
10032         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10033 }
10034
10035 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10036 {
10037         // transparent surfaces get pushed off into the transparent queue
10038         int surfacelistindex;
10039         const msurface_t *surface;
10040         vec3_t tempcenter, center;
10041         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10042         {
10043                 surface = texturesurfacelist[surfacelistindex];
10044                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10045                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10046                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10047                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10048                 if (queueentity->transparent_offset) // transparent offset
10049                 {
10050                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10051                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10052                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10053                 }
10054                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10055         }
10056 }
10057
10058 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10059 {
10060         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10061                 return;
10062         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10063                 return;
10064         RSurf_SetupDepthAndCulling();
10065         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10066         if (rsurface.batchvertex3fbuffer)
10067                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10068         else
10069                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10070         RSurf_DrawBatch();
10071 }
10072
10073 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10074 {
10075         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10076         CHECKGLERROR
10077         if (depthonly)
10078                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10079         else if (prepass)
10080         {
10081                 if (!rsurface.texture->currentnumlayers)
10082                         return;
10083                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10084                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10085                 else
10086                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10087         }
10088         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10089                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10090         else if (!rsurface.texture->currentnumlayers)
10091                 return;
10092         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10093         {
10094                 // in the deferred case, transparent surfaces were queued during prepass
10095                 if (!r_shadow_usingdeferredprepass)
10096                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10097         }
10098         else
10099         {
10100                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10101                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10102         }
10103         CHECKGLERROR
10104 }
10105
10106 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10107 {
10108         int i, j;
10109         texture_t *texture;
10110         R_FrameData_SetMark();
10111         // break the surface list down into batches by texture and use of lightmapping
10112         for (i = 0;i < numsurfaces;i = j)
10113         {
10114                 j = i + 1;
10115                 // texture is the base texture pointer, rsurface.texture is the
10116                 // current frame/skin the texture is directing us to use (for example
10117                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10118                 // use skin 1 instead)
10119                 texture = surfacelist[i]->texture;
10120                 rsurface.texture = R_GetCurrentTexture(texture);
10121                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10122                 {
10123                         // if this texture is not the kind we want, skip ahead to the next one
10124                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10125                                 ;
10126                         continue;
10127                 }
10128                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10129                 {
10130                         rsurface.lightmaptexture = NULL;
10131                         rsurface.deluxemaptexture = NULL;
10132                         rsurface.uselightmaptexture = false;
10133                         // simply scan ahead until we find a different texture or lightmap state
10134                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10135                                 ;
10136                 }
10137                 else
10138                 {
10139                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10140                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10141                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10142                         // simply scan ahead until we find a different texture or lightmap state
10143                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10144                                 ;
10145                 }
10146                 // render the range of surfaces
10147                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10148         }
10149         R_FrameData_ReturnToMark();
10150 }
10151
10152 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10153 {
10154         CHECKGLERROR
10155         if (depthonly)
10156                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10157         else if (prepass)
10158         {
10159                 if (!rsurface.texture->currentnumlayers)
10160                         return;
10161                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10162                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10163                 else
10164                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10165         }
10166         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10167                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10168         else if (!rsurface.texture->currentnumlayers)
10169                 return;
10170         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10171         {
10172                 // in the deferred case, transparent surfaces were queued during prepass
10173                 if (!r_shadow_usingdeferredprepass)
10174                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10175         }
10176         else
10177         {
10178                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10179                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10180         }
10181         CHECKGLERROR
10182 }
10183
10184 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10185 {
10186         int i, j;
10187         texture_t *texture;
10188         R_FrameData_SetMark();
10189         // break the surface list down into batches by texture and use of lightmapping
10190         for (i = 0;i < numsurfaces;i = j)
10191         {
10192                 j = i + 1;
10193                 // texture is the base texture pointer, rsurface.texture is the
10194                 // current frame/skin the texture is directing us to use (for example
10195                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10196                 // use skin 1 instead)
10197                 texture = surfacelist[i]->texture;
10198                 rsurface.texture = R_GetCurrentTexture(texture);
10199                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10200                 {
10201                         // if this texture is not the kind we want, skip ahead to the next one
10202                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10203                                 ;
10204                         continue;
10205                 }
10206                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10207                 {
10208                         rsurface.lightmaptexture = NULL;
10209                         rsurface.deluxemaptexture = NULL;
10210                         rsurface.uselightmaptexture = false;
10211                         // simply scan ahead until we find a different texture or lightmap state
10212                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10213                                 ;
10214                 }
10215                 else
10216                 {
10217                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10218                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10219                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10220                         // simply scan ahead until we find a different texture or lightmap state
10221                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10222                                 ;
10223                 }
10224                 // render the range of surfaces
10225                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10226         }
10227         R_FrameData_ReturnToMark();
10228 }
10229
10230 float locboxvertex3f[6*4*3] =
10231 {
10232         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10233         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10234         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10235         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10236         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10237         1,0,0, 0,0,0, 0,1,0, 1,1,0
10238 };
10239
10240 unsigned short locboxelements[6*2*3] =
10241 {
10242          0, 1, 2, 0, 2, 3,
10243          4, 5, 6, 4, 6, 7,
10244          8, 9,10, 8,10,11,
10245         12,13,14, 12,14,15,
10246         16,17,18, 16,18,19,
10247         20,21,22, 20,22,23
10248 };
10249
10250 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10251 {
10252         int i, j;
10253         cl_locnode_t *loc = (cl_locnode_t *)ent;
10254         vec3_t mins, size;
10255         float vertex3f[6*4*3];
10256         CHECKGLERROR
10257         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10258         GL_DepthMask(false);
10259         GL_DepthRange(0, 1);
10260         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10261         GL_DepthTest(true);
10262         GL_CullFace(GL_NONE);
10263         R_EntityMatrix(&identitymatrix);
10264
10265 //      R_Mesh_ResetTextureState();
10266
10267         i = surfacelist[0];
10268         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10269                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10270                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10271                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10272
10273         if (VectorCompare(loc->mins, loc->maxs))
10274         {
10275                 VectorSet(size, 2, 2, 2);
10276                 VectorMA(loc->mins, -0.5f, size, mins);
10277         }
10278         else
10279         {
10280                 VectorCopy(loc->mins, mins);
10281                 VectorSubtract(loc->maxs, loc->mins, size);
10282         }
10283
10284         for (i = 0;i < 6*4*3;)
10285                 for (j = 0;j < 3;j++, i++)
10286                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10287
10288         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10289         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10290         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10291 }
10292
10293 void R_DrawLocs(void)
10294 {
10295         int index;
10296         cl_locnode_t *loc, *nearestloc;
10297         vec3_t center;
10298         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10299         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10300         {
10301                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10302                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10303         }
10304 }
10305
10306 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10307 {
10308         if (decalsystem->decals)
10309                 Mem_Free(decalsystem->decals);
10310         memset(decalsystem, 0, sizeof(*decalsystem));
10311 }
10312
10313 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)
10314 {
10315         tridecal_t *decal;
10316         tridecal_t *decals;
10317         int i;
10318
10319         // expand or initialize the system
10320         if (decalsystem->maxdecals <= decalsystem->numdecals)
10321         {
10322                 decalsystem_t old = *decalsystem;
10323                 qboolean useshortelements;
10324                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10325                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10326                 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)));
10327                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10328                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10329                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10330                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10331                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10332                 if (decalsystem->numdecals)
10333                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10334                 if (old.decals)
10335                         Mem_Free(old.decals);
10336                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10337                         decalsystem->element3i[i] = i;
10338                 if (useshortelements)
10339                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10340                                 decalsystem->element3s[i] = i;
10341         }
10342
10343         // grab a decal and search for another free slot for the next one
10344         decals = decalsystem->decals;
10345         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10346         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10347                 ;
10348         decalsystem->freedecal = i;
10349         if (decalsystem->numdecals <= i)
10350                 decalsystem->numdecals = i + 1;
10351
10352         // initialize the decal
10353         decal->lived = 0;
10354         decal->triangleindex = triangleindex;
10355         decal->surfaceindex = surfaceindex;
10356         decal->decalsequence = decalsequence;
10357         decal->color4f[0][0] = c0[0];
10358         decal->color4f[0][1] = c0[1];
10359         decal->color4f[0][2] = c0[2];
10360         decal->color4f[0][3] = 1;
10361         decal->color4f[1][0] = c1[0];
10362         decal->color4f[1][1] = c1[1];
10363         decal->color4f[1][2] = c1[2];
10364         decal->color4f[1][3] = 1;
10365         decal->color4f[2][0] = c2[0];
10366         decal->color4f[2][1] = c2[1];
10367         decal->color4f[2][2] = c2[2];
10368         decal->color4f[2][3] = 1;
10369         decal->vertex3f[0][0] = v0[0];
10370         decal->vertex3f[0][1] = v0[1];
10371         decal->vertex3f[0][2] = v0[2];
10372         decal->vertex3f[1][0] = v1[0];
10373         decal->vertex3f[1][1] = v1[1];
10374         decal->vertex3f[1][2] = v1[2];
10375         decal->vertex3f[2][0] = v2[0];
10376         decal->vertex3f[2][1] = v2[1];
10377         decal->vertex3f[2][2] = v2[2];
10378         decal->texcoord2f[0][0] = t0[0];
10379         decal->texcoord2f[0][1] = t0[1];
10380         decal->texcoord2f[1][0] = t1[0];
10381         decal->texcoord2f[1][1] = t1[1];
10382         decal->texcoord2f[2][0] = t2[0];
10383         decal->texcoord2f[2][1] = t2[1];
10384 }
10385
10386 extern cvar_t cl_decals_bias;
10387 extern cvar_t cl_decals_models;
10388 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10389 // baseparms, parms, temps
10390 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)
10391 {
10392         int cornerindex;
10393         int index;
10394         float v[9][3];
10395         const float *vertex3f;
10396         const float *normal3f;
10397         int numpoints;
10398         float points[2][9][3];
10399         float temp[3];
10400         float tc[9][2];
10401         float f;
10402         float c[9][4];
10403         const int *e;
10404
10405         e = rsurface.modelelement3i + 3*triangleindex;
10406
10407         vertex3f = rsurface.modelvertex3f;
10408         normal3f = rsurface.modelnormal3f;
10409
10410         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10411         {
10412                 index = 3*e[cornerindex];
10413                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10414         }
10415         // cull backfaces
10416         //TriangleNormal(v[0], v[1], v[2], normal);
10417         //if (DotProduct(normal, localnormal) < 0.0f)
10418         //      continue;
10419         // clip by each of the box planes formed from the projection matrix
10420         // if anything survives, we emit the decal
10421         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]);
10422         if (numpoints < 3)
10423                 return;
10424         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]);
10425         if (numpoints < 3)
10426                 return;
10427         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]);
10428         if (numpoints < 3)
10429                 return;
10430         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]);
10431         if (numpoints < 3)
10432                 return;
10433         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]);
10434         if (numpoints < 3)
10435                 return;
10436         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]);
10437         if (numpoints < 3)
10438                 return;
10439         // some part of the triangle survived, so we have to accept it...
10440         if (dynamic)
10441         {
10442                 // dynamic always uses the original triangle
10443                 numpoints = 3;
10444                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10445                 {
10446                         index = 3*e[cornerindex];
10447                         VectorCopy(vertex3f + index, v[cornerindex]);
10448                 }
10449         }
10450         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10451         {
10452                 // convert vertex positions to texcoords
10453                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10454                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10455                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10456                 // calculate distance fade from the projection origin
10457                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10458                 f = bound(0.0f, f, 1.0f);
10459                 c[cornerindex][0] = r * f;
10460                 c[cornerindex][1] = g * f;
10461                 c[cornerindex][2] = b * f;
10462                 c[cornerindex][3] = 1.0f;
10463                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10464         }
10465         if (dynamic)
10466                 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);
10467         else
10468                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10469                         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);
10470 }
10471 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)
10472 {
10473         matrix4x4_t projection;
10474         decalsystem_t *decalsystem;
10475         qboolean dynamic;
10476         dp_model_t *model;
10477         const msurface_t *surface;
10478         const msurface_t *surfaces;
10479         const int *surfacelist;
10480         const texture_t *texture;
10481         int numtriangles;
10482         int numsurfacelist;
10483         int surfacelistindex;
10484         int surfaceindex;
10485         int triangleindex;
10486         float localorigin[3];
10487         float localnormal[3];
10488         float localmins[3];
10489         float localmaxs[3];
10490         float localsize;
10491         //float normal[3];
10492         float planes[6][4];
10493         float angles[3];
10494         bih_t *bih;
10495         int bih_triangles_count;
10496         int bih_triangles[256];
10497         int bih_surfaces[256];
10498
10499         decalsystem = &ent->decalsystem;
10500         model = ent->model;
10501         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10502         {
10503                 R_DecalSystem_Reset(&ent->decalsystem);
10504                 return;
10505         }
10506
10507         if (!model->brush.data_leafs && !cl_decals_models.integer)
10508         {
10509                 if (decalsystem->model)
10510                         R_DecalSystem_Reset(decalsystem);
10511                 return;
10512         }
10513
10514         if (decalsystem->model != model)
10515                 R_DecalSystem_Reset(decalsystem);
10516         decalsystem->model = model;
10517
10518         RSurf_ActiveModelEntity(ent, true, false, false);
10519
10520         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10521         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10522         VectorNormalize(localnormal);
10523         localsize = worldsize*rsurface.inversematrixscale;
10524         localmins[0] = localorigin[0] - localsize;
10525         localmins[1] = localorigin[1] - localsize;
10526         localmins[2] = localorigin[2] - localsize;
10527         localmaxs[0] = localorigin[0] + localsize;
10528         localmaxs[1] = localorigin[1] + localsize;
10529         localmaxs[2] = localorigin[2] + localsize;
10530
10531         //VectorCopy(localnormal, planes[4]);
10532         //VectorVectors(planes[4], planes[2], planes[0]);
10533         AnglesFromVectors(angles, localnormal, NULL, false);
10534         AngleVectors(angles, planes[0], planes[2], planes[4]);
10535         VectorNegate(planes[0], planes[1]);
10536         VectorNegate(planes[2], planes[3]);
10537         VectorNegate(planes[4], planes[5]);
10538         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10539         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10540         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10541         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10542         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10543         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10544
10545 #if 1
10546 // works
10547 {
10548         matrix4x4_t forwardprojection;
10549         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10550         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10551 }
10552 #else
10553 // broken
10554 {
10555         float projectionvector[4][3];
10556         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10557         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10558         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10559         projectionvector[0][0] = planes[0][0] * ilocalsize;
10560         projectionvector[0][1] = planes[1][0] * ilocalsize;
10561         projectionvector[0][2] = planes[2][0] * ilocalsize;
10562         projectionvector[1][0] = planes[0][1] * ilocalsize;
10563         projectionvector[1][1] = planes[1][1] * ilocalsize;
10564         projectionvector[1][2] = planes[2][1] * ilocalsize;
10565         projectionvector[2][0] = planes[0][2] * ilocalsize;
10566         projectionvector[2][1] = planes[1][2] * ilocalsize;
10567         projectionvector[2][2] = planes[2][2] * ilocalsize;
10568         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10569         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10570         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10571         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10572 }
10573 #endif
10574
10575         dynamic = model->surfmesh.isanimated;
10576         numsurfacelist = model->nummodelsurfaces;
10577         surfacelist = model->sortedmodelsurfaces;
10578         surfaces = model->data_surfaces;
10579
10580         bih = NULL;
10581         bih_triangles_count = -1;
10582         if(!dynamic)
10583         {
10584                 if(model->render_bih.numleafs)
10585                         bih = &model->render_bih;
10586                 else if(model->collision_bih.numleafs)
10587                         bih = &model->collision_bih;
10588         }
10589         if(bih)
10590                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10591         if(bih_triangles_count == 0)
10592                 return;
10593         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10594                 return;
10595         if(bih_triangles_count > 0)
10596         {
10597                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10598                 {
10599                         surfaceindex = bih_surfaces[triangleindex];
10600                         surface = surfaces + surfaceindex;
10601                         texture = surface->texture;
10602                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10603                                 continue;
10604                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10605                                 continue;
10606                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10607                 }
10608         }
10609         else
10610         {
10611                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10612                 {
10613                         surfaceindex = surfacelist[surfacelistindex];
10614                         surface = surfaces + surfaceindex;
10615                         // check cull box first because it rejects more than any other check
10616                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10617                                 continue;
10618                         // skip transparent surfaces
10619                         texture = surface->texture;
10620                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10621                                 continue;
10622                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10623                                 continue;
10624                         numtriangles = surface->num_triangles;
10625                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10626                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10627                 }
10628         }
10629 }
10630
10631 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10632 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)
10633 {
10634         int renderentityindex;
10635         float worldmins[3];
10636         float worldmaxs[3];
10637         entity_render_t *ent;
10638
10639         if (!cl_decals_newsystem.integer)
10640                 return;
10641
10642         worldmins[0] = worldorigin[0] - worldsize;
10643         worldmins[1] = worldorigin[1] - worldsize;
10644         worldmins[2] = worldorigin[2] - worldsize;
10645         worldmaxs[0] = worldorigin[0] + worldsize;
10646         worldmaxs[1] = worldorigin[1] + worldsize;
10647         worldmaxs[2] = worldorigin[2] + worldsize;
10648
10649         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10650
10651         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10652         {
10653                 ent = r_refdef.scene.entities[renderentityindex];
10654                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10655                         continue;
10656
10657                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10658         }
10659 }
10660
10661 typedef struct r_decalsystem_splatqueue_s
10662 {
10663         vec3_t worldorigin;
10664         vec3_t worldnormal;
10665         float color[4];
10666         float tcrange[4];
10667         float worldsize;
10668         int decalsequence;
10669 }
10670 r_decalsystem_splatqueue_t;
10671
10672 int r_decalsystem_numqueued = 0;
10673 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10674
10675 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)
10676 {
10677         r_decalsystem_splatqueue_t *queue;
10678
10679         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10680                 return;
10681
10682         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10683         VectorCopy(worldorigin, queue->worldorigin);
10684         VectorCopy(worldnormal, queue->worldnormal);
10685         Vector4Set(queue->color, r, g, b, a);
10686         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10687         queue->worldsize = worldsize;
10688         queue->decalsequence = cl.decalsequence++;
10689 }
10690
10691 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10692 {
10693         int i;
10694         r_decalsystem_splatqueue_t *queue;
10695
10696         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10697                 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);
10698         r_decalsystem_numqueued = 0;
10699 }
10700
10701 extern cvar_t cl_decals_max;
10702 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10703 {
10704         int i;
10705         decalsystem_t *decalsystem = &ent->decalsystem;
10706         int numdecals;
10707         int killsequence;
10708         tridecal_t *decal;
10709         float frametime;
10710         float lifetime;
10711
10712         if (!decalsystem->numdecals)
10713                 return;
10714
10715         if (r_showsurfaces.integer)
10716                 return;
10717
10718         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10719         {
10720                 R_DecalSystem_Reset(decalsystem);
10721                 return;
10722         }
10723
10724         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10725         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10726
10727         if (decalsystem->lastupdatetime)
10728                 frametime = (cl.time - decalsystem->lastupdatetime);
10729         else
10730                 frametime = 0;
10731         decalsystem->lastupdatetime = cl.time;
10732         decal = decalsystem->decals;
10733         numdecals = decalsystem->numdecals;
10734
10735         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10736         {
10737                 if (decal->color4f[0][3])
10738                 {
10739                         decal->lived += frametime;
10740                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10741                         {
10742                                 memset(decal, 0, sizeof(*decal));
10743                                 if (decalsystem->freedecal > i)
10744                                         decalsystem->freedecal = i;
10745                         }
10746                 }
10747         }
10748         decal = decalsystem->decals;
10749         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10750                 numdecals--;
10751
10752         // collapse the array by shuffling the tail decals into the gaps
10753         for (;;)
10754         {
10755                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10756                         decalsystem->freedecal++;
10757                 if (decalsystem->freedecal == numdecals)
10758                         break;
10759                 decal[decalsystem->freedecal] = decal[--numdecals];
10760         }
10761
10762         decalsystem->numdecals = numdecals;
10763
10764         if (numdecals <= 0)
10765         {
10766                 // if there are no decals left, reset decalsystem
10767                 R_DecalSystem_Reset(decalsystem);
10768         }
10769 }
10770
10771 extern skinframe_t *decalskinframe;
10772 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10773 {
10774         int i;
10775         decalsystem_t *decalsystem = &ent->decalsystem;
10776         int numdecals;
10777         tridecal_t *decal;
10778         float faderate;
10779         float alpha;
10780         float *v3f;
10781         float *c4f;
10782         float *t2f;
10783         const int *e;
10784         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10785         int numtris = 0;
10786
10787         numdecals = decalsystem->numdecals;
10788         if (!numdecals)
10789                 return;
10790
10791         if (r_showsurfaces.integer)
10792                 return;
10793
10794         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10795         {
10796                 R_DecalSystem_Reset(decalsystem);
10797                 return;
10798         }
10799
10800         // if the model is static it doesn't matter what value we give for
10801         // wantnormals and wanttangents, so this logic uses only rules applicable
10802         // to a model, knowing that they are meaningless otherwise
10803         if (ent == r_refdef.scene.worldentity)
10804                 RSurf_ActiveWorldEntity();
10805         else
10806                 RSurf_ActiveModelEntity(ent, false, false, false);
10807
10808         decalsystem->lastupdatetime = cl.time;
10809         decal = decalsystem->decals;
10810
10811         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10812
10813         // update vertex positions for animated models
10814         v3f = decalsystem->vertex3f;
10815         c4f = decalsystem->color4f;
10816         t2f = decalsystem->texcoord2f;
10817         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10818         {
10819                 if (!decal->color4f[0][3])
10820                         continue;
10821
10822                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10823                         continue;
10824
10825                 // update color values for fading decals
10826                 if (decal->lived >= cl_decals_time.value)
10827                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10828                 else
10829                         alpha = 1.0f;
10830
10831                 c4f[ 0] = decal->color4f[0][0] * alpha;
10832                 c4f[ 1] = decal->color4f[0][1] * alpha;
10833                 c4f[ 2] = decal->color4f[0][2] * alpha;
10834                 c4f[ 3] = 1;
10835                 c4f[ 4] = decal->color4f[1][0] * alpha;
10836                 c4f[ 5] = decal->color4f[1][1] * alpha;
10837                 c4f[ 6] = decal->color4f[1][2] * alpha;
10838                 c4f[ 7] = 1;
10839                 c4f[ 8] = decal->color4f[2][0] * alpha;
10840                 c4f[ 9] = decal->color4f[2][1] * alpha;
10841                 c4f[10] = decal->color4f[2][2] * alpha;
10842                 c4f[11] = 1;
10843
10844                 t2f[0] = decal->texcoord2f[0][0];
10845                 t2f[1] = decal->texcoord2f[0][1];
10846                 t2f[2] = decal->texcoord2f[1][0];
10847                 t2f[3] = decal->texcoord2f[1][1];
10848                 t2f[4] = decal->texcoord2f[2][0];
10849                 t2f[5] = decal->texcoord2f[2][1];
10850
10851                 // update vertex positions for animated models
10852                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10853                 {
10854                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10855                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10856                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10857                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10858                 }
10859                 else
10860                 {
10861                         VectorCopy(decal->vertex3f[0], v3f);
10862                         VectorCopy(decal->vertex3f[1], v3f + 3);
10863                         VectorCopy(decal->vertex3f[2], v3f + 6);
10864                 }
10865
10866                 if (r_refdef.fogenabled)
10867                 {
10868                         alpha = RSurf_FogVertex(v3f);
10869                         VectorScale(c4f, alpha, c4f);
10870                         alpha = RSurf_FogVertex(v3f + 3);
10871                         VectorScale(c4f + 4, alpha, c4f + 4);
10872                         alpha = RSurf_FogVertex(v3f + 6);
10873                         VectorScale(c4f + 8, alpha, c4f + 8);
10874                 }
10875
10876                 v3f += 9;
10877                 c4f += 12;
10878                 t2f += 6;
10879                 numtris++;
10880         }
10881
10882         if (numtris > 0)
10883         {
10884                 r_refdef.stats.drawndecals += numtris;
10885
10886                 // now render the decals all at once
10887                 // (this assumes they all use one particle font texture!)
10888                 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);
10889 //              R_Mesh_ResetTextureState();
10890                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10891                 GL_DepthMask(false);
10892                 GL_DepthRange(0, 1);
10893                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10894                 GL_DepthTest(true);
10895                 GL_CullFace(GL_NONE);
10896                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10897                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10898                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10899         }
10900 }
10901
10902 static void R_DrawModelDecals(void)
10903 {
10904         int i, numdecals;
10905
10906         // fade faster when there are too many decals
10907         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10908         for (i = 0;i < r_refdef.scene.numentities;i++)
10909                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10910
10911         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10912         for (i = 0;i < r_refdef.scene.numentities;i++)
10913                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10914                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10915
10916         R_DecalSystem_ApplySplatEntitiesQueue();
10917
10918         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10919         for (i = 0;i < r_refdef.scene.numentities;i++)
10920                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10921
10922         r_refdef.stats.totaldecals += numdecals;
10923
10924         if (r_showsurfaces.integer)
10925                 return;
10926
10927         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10928
10929         for (i = 0;i < r_refdef.scene.numentities;i++)
10930         {
10931                 if (!r_refdef.viewcache.entityvisible[i])
10932                         continue;
10933                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10934                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10935         }
10936 }
10937
10938 extern cvar_t mod_collision_bih;
10939 void R_DrawDebugModel(void)
10940 {
10941         entity_render_t *ent = rsurface.entity;
10942         int i, j, k, l, flagsmask;
10943         const msurface_t *surface;
10944         dp_model_t *model = ent->model;
10945         vec3_t v;
10946
10947         switch(vid.renderpath)
10948         {
10949         case RENDERPATH_GL11:
10950         case RENDERPATH_GL13:
10951         case RENDERPATH_GL20:
10952                 break;
10953         case RENDERPATH_D3D9:
10954                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10955                 return;
10956         case RENDERPATH_D3D10:
10957                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10958                 return;
10959         case RENDERPATH_D3D11:
10960                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10961                 return;
10962         case RENDERPATH_SOFT:
10963                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10964                 return;
10965         case RENDERPATH_GLES2:
10966                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10967                 return;
10968         }
10969
10970         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10971
10972 //      R_Mesh_ResetTextureState();
10973         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10974         GL_DepthRange(0, 1);
10975         GL_DepthTest(!r_showdisabledepthtest.integer);
10976         GL_DepthMask(false);
10977         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10978
10979         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10980         {
10981                 int triangleindex;
10982                 int bihleafindex;
10983                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10984                 const q3mbrush_t *brush;
10985                 const bih_t *bih = &model->collision_bih;
10986                 const bih_leaf_t *bihleaf;
10987                 float vertex3f[3][3];
10988                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10989                 cullbox = false;
10990                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10991                 {
10992                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10993                                 continue;
10994                         switch (bihleaf->type)
10995                         {
10996                         case BIH_BRUSH:
10997                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10998                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10999                                 {
11000                                         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);
11001                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11002                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11003                                 }
11004                                 break;
11005                         case BIH_COLLISIONTRIANGLE:
11006                                 triangleindex = bihleaf->itemindex;
11007                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11008                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11009                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11010                                 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);
11011                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11012                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11013                                 break;
11014                         case BIH_RENDERTRIANGLE:
11015                                 triangleindex = bihleaf->itemindex;
11016                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11017                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11018                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11019                                 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);
11020                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11021                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11022                                 break;
11023                         }
11024                 }
11025         }
11026
11027         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11028
11029         if (r_showtris.integer || (r_shownormals.value != 0))
11030         {
11031                 if (r_showdisabledepthtest.integer)
11032                 {
11033                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11034                         GL_DepthMask(false);
11035                 }
11036                 else
11037                 {
11038                         GL_BlendFunc(GL_ONE, GL_ZERO);
11039                         GL_DepthMask(true);
11040                 }
11041                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11042                 {
11043                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11044                                 continue;
11045                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11046                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11047                         {
11048                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11049                                 if (r_showtris.value > 0)
11050                                 {
11051                                         if (!rsurface.texture->currentlayers->depthmask)
11052                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11053                                         else if (ent == r_refdef.scene.worldentity)
11054                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11055                                         else
11056                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11057                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11058                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11059                                         RSurf_DrawBatch();
11060                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11061                                         CHECKGLERROR
11062                                 }
11063                                 if (r_shownormals.value < 0)
11064                                 {
11065                                         qglBegin(GL_LINES);
11066                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11067                                         {
11068                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11069                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11070                                                 qglVertex3f(v[0], v[1], v[2]);
11071                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11072                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11073                                                 qglVertex3f(v[0], v[1], v[2]);
11074                                         }
11075                                         qglEnd();
11076                                         CHECKGLERROR
11077                                 }
11078                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11079                                 {
11080                                         qglBegin(GL_LINES);
11081                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11082                                         {
11083                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11084                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11085                                                 qglVertex3f(v[0], v[1], v[2]);
11086                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11087                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11088                                                 qglVertex3f(v[0], v[1], v[2]);
11089                                         }
11090                                         qglEnd();
11091                                         CHECKGLERROR
11092                                         qglBegin(GL_LINES);
11093                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11094                                         {
11095                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11096                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11097                                                 qglVertex3f(v[0], v[1], v[2]);
11098                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11099                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11100                                                 qglVertex3f(v[0], v[1], v[2]);
11101                                         }
11102                                         qglEnd();
11103                                         CHECKGLERROR
11104                                         qglBegin(GL_LINES);
11105                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11106                                         {
11107                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11108                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11109                                                 qglVertex3f(v[0], v[1], v[2]);
11110                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11111                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11112                                                 qglVertex3f(v[0], v[1], v[2]);
11113                                         }
11114                                         qglEnd();
11115                                         CHECKGLERROR
11116                                 }
11117                         }
11118                 }
11119                 rsurface.texture = NULL;
11120         }
11121 }
11122
11123 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11124 int r_maxsurfacelist = 0;
11125 const msurface_t **r_surfacelist = NULL;
11126 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11127 {
11128         int i, j, endj, flagsmask;
11129         dp_model_t *model = r_refdef.scene.worldmodel;
11130         msurface_t *surfaces;
11131         unsigned char *update;
11132         int numsurfacelist = 0;
11133         if (model == NULL)
11134                 return;
11135
11136         if (r_maxsurfacelist < model->num_surfaces)
11137         {
11138                 r_maxsurfacelist = model->num_surfaces;
11139                 if (r_surfacelist)
11140                         Mem_Free((msurface_t**)r_surfacelist);
11141                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11142         }
11143
11144         RSurf_ActiveWorldEntity();
11145
11146         surfaces = model->data_surfaces;
11147         update = model->brushq1.lightmapupdateflags;
11148
11149         // update light styles on this submodel
11150         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11151         {
11152                 model_brush_lightstyleinfo_t *style;
11153                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11154                 {
11155                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11156                         {
11157                                 int *list = style->surfacelist;
11158                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11159                                 for (j = 0;j < style->numsurfaces;j++)
11160                                         update[list[j]] = true;
11161                         }
11162                 }
11163         }
11164
11165         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11166
11167         if (debug)
11168         {
11169                 R_DrawDebugModel();
11170                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11171                 return;
11172         }
11173
11174         rsurface.lightmaptexture = NULL;
11175         rsurface.deluxemaptexture = NULL;
11176         rsurface.uselightmaptexture = false;
11177         rsurface.texture = NULL;
11178         rsurface.rtlight = NULL;
11179         numsurfacelist = 0;
11180         // add visible surfaces to draw list
11181         for (i = 0;i < model->nummodelsurfaces;i++)
11182         {
11183                 j = model->sortedmodelsurfaces[i];
11184                 if (r_refdef.viewcache.world_surfacevisible[j])
11185                         r_surfacelist[numsurfacelist++] = surfaces + j;
11186         }
11187         // update lightmaps if needed
11188         if (model->brushq1.firstrender)
11189         {
11190                 model->brushq1.firstrender = false;
11191                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11192                         if (update[j])
11193                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11194         }
11195         else if (update)
11196         {
11197                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11198                         if (r_refdef.viewcache.world_surfacevisible[j])
11199                                 if (update[j])
11200                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11201         }
11202         // don't do anything if there were no surfaces
11203         if (!numsurfacelist)
11204         {
11205                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11206                 return;
11207         }
11208         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11209
11210         // add to stats if desired
11211         if (r_speeds.integer && !skysurfaces && !depthonly)
11212         {
11213                 r_refdef.stats.world_surfaces += numsurfacelist;
11214                 for (j = 0;j < numsurfacelist;j++)
11215                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11216         }
11217
11218         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11219 }
11220
11221 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11222 {
11223         int i, j, endj, flagsmask;
11224         dp_model_t *model = ent->model;
11225         msurface_t *surfaces;
11226         unsigned char *update;
11227         int numsurfacelist = 0;
11228         if (model == NULL)
11229                 return;
11230
11231         if (r_maxsurfacelist < model->num_surfaces)
11232         {
11233                 r_maxsurfacelist = model->num_surfaces;
11234                 if (r_surfacelist)
11235                         Mem_Free((msurface_t **)r_surfacelist);
11236                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11237         }
11238
11239         // if the model is static it doesn't matter what value we give for
11240         // wantnormals and wanttangents, so this logic uses only rules applicable
11241         // to a model, knowing that they are meaningless otherwise
11242         if (ent == r_refdef.scene.worldentity)
11243                 RSurf_ActiveWorldEntity();
11244         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11245                 RSurf_ActiveModelEntity(ent, false, false, false);
11246         else if (prepass)
11247                 RSurf_ActiveModelEntity(ent, true, true, true);
11248         else if (depthonly)
11249         {
11250                 switch (vid.renderpath)
11251                 {
11252                 case RENDERPATH_GL20:
11253                 case RENDERPATH_D3D9:
11254                 case RENDERPATH_D3D10:
11255                 case RENDERPATH_D3D11:
11256                 case RENDERPATH_SOFT:
11257                 case RENDERPATH_GLES2:
11258                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11259                         break;
11260                 case RENDERPATH_GL13:
11261                 case RENDERPATH_GL11:
11262                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11263                         break;
11264                 }
11265         }
11266         else
11267         {
11268                 switch (vid.renderpath)
11269                 {
11270                 case RENDERPATH_GL20:
11271                 case RENDERPATH_D3D9:
11272                 case RENDERPATH_D3D10:
11273                 case RENDERPATH_D3D11:
11274                 case RENDERPATH_SOFT:
11275                 case RENDERPATH_GLES2:
11276                         RSurf_ActiveModelEntity(ent, true, true, false);
11277                         break;
11278                 case RENDERPATH_GL13:
11279                 case RENDERPATH_GL11:
11280                         RSurf_ActiveModelEntity(ent, true, false, false);
11281                         break;
11282                 }
11283         }
11284
11285         surfaces = model->data_surfaces;
11286         update = model->brushq1.lightmapupdateflags;
11287
11288         // update light styles
11289         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11290         {
11291                 model_brush_lightstyleinfo_t *style;
11292                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11293                 {
11294                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11295                         {
11296                                 int *list = style->surfacelist;
11297                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11298                                 for (j = 0;j < style->numsurfaces;j++)
11299                                         update[list[j]] = true;
11300                         }
11301                 }
11302         }
11303
11304         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11305
11306         if (debug)
11307         {
11308                 R_DrawDebugModel();
11309                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11310                 return;
11311         }
11312
11313         rsurface.lightmaptexture = NULL;
11314         rsurface.deluxemaptexture = NULL;
11315         rsurface.uselightmaptexture = false;
11316         rsurface.texture = NULL;
11317         rsurface.rtlight = NULL;
11318         numsurfacelist = 0;
11319         // add visible surfaces to draw list
11320         for (i = 0;i < model->nummodelsurfaces;i++)
11321                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11322         // don't do anything if there were no surfaces
11323         if (!numsurfacelist)
11324         {
11325                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11326                 return;
11327         }
11328         // update lightmaps if needed
11329         if (update)
11330         {
11331                 int updated = 0;
11332                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11333                 {
11334                         if (update[j])
11335                         {
11336                                 updated++;
11337                                 R_BuildLightMap(ent, surfaces + j);
11338                         }
11339                 }
11340         }
11341         if (update)
11342                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11343                         if (update[j])
11344                                 R_BuildLightMap(ent, surfaces + j);
11345         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11346
11347         // add to stats if desired
11348         if (r_speeds.integer && !skysurfaces && !depthonly)
11349         {
11350                 r_refdef.stats.entities_surfaces += numsurfacelist;
11351                 for (j = 0;j < numsurfacelist;j++)
11352                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11353         }
11354
11355         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11356 }
11357
11358 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11359 {
11360         static texture_t texture;
11361         static msurface_t surface;
11362         const msurface_t *surfacelist = &surface;
11363
11364         // fake enough texture and surface state to render this geometry
11365
11366         texture.update_lastrenderframe = -1; // regenerate this texture
11367         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11368         texture.currentskinframe = skinframe;
11369         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11370         texture.offsetmapping = OFFSETMAPPING_OFF;
11371         texture.offsetscale = 1;
11372         texture.specularscalemod = 1;
11373         texture.specularpowermod = 1;
11374
11375         surface.texture = &texture;
11376         surface.num_triangles = numtriangles;
11377         surface.num_firsttriangle = firsttriangle;
11378         surface.num_vertices = numvertices;
11379         surface.num_firstvertex = firstvertex;
11380
11381         // now render it
11382         rsurface.texture = R_GetCurrentTexture(surface.texture);
11383         rsurface.lightmaptexture = NULL;
11384         rsurface.deluxemaptexture = NULL;
11385         rsurface.uselightmaptexture = false;
11386         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11387 }
11388
11389 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)
11390 {
11391         static msurface_t surface;
11392         const msurface_t *surfacelist = &surface;
11393
11394         // fake enough texture and surface state to render this geometry
11395         surface.texture = texture;
11396         surface.num_triangles = numtriangles;
11397         surface.num_firsttriangle = firsttriangle;
11398         surface.num_vertices = numvertices;
11399         surface.num_firstvertex = firstvertex;
11400
11401         // now render it
11402         rsurface.texture = R_GetCurrentTexture(surface.texture);
11403         rsurface.lightmaptexture = NULL;
11404         rsurface.deluxemaptexture = NULL;
11405         rsurface.uselightmaptexture = false;
11406         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11407 }