]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
also turn off fog on blendfuncs that cannot handle it
[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(!allow_fog)
2543                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2544         switch(vid.renderpath)
2545         {
2546         case RENDERPATH_D3D9:
2547 #ifdef SUPPORTD3D
2548                 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);
2549                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2550                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2552                 if (mode == SHADERMODE_LIGHTSOURCE)
2553                 {
2554                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2555                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2556                 }
2557                 else
2558                 {
2559                         if (mode == SHADERMODE_LIGHTDIRECTION)
2560                         {
2561                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2562                         }
2563                 }
2564                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2565                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2566                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2567                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2568                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2569
2570                 if (mode == SHADERMODE_LIGHTSOURCE)
2571                 {
2572                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2573                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2574                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2575                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2576                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2577
2578                         // additive passes are only darkened by fog, not tinted
2579                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2580                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2581                 }
2582                 else
2583                 {
2584                         if (mode == SHADERMODE_FLATCOLOR)
2585                         {
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2587                         }
2588                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2589                         {
2590                                 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]);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2592                                 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);
2593                                 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);
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2597                         }
2598                         else
2599                         {
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2602                                 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);
2603                                 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);
2604                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2605                         }
2606                         // additive passes are only darkened by fog, not tinted
2607                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2608                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2609                         else
2610                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2611                         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);
2612                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2613                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2614                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2615                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2616                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2617                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2618                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2619                         if (mode == SHADERMODE_WATER)
2620                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2621                 }
2622                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2623                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2624                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2625                 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));
2626                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2627                 if (rsurface.texture->pantstexture)
2628                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2629                 else
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2631                 if (rsurface.texture->shirttexture)
2632                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2633                 else
2634                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2635                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2636                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2637                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2638                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2639                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2640                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2641                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2642
2643                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2644                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2645                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2646                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2648                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2649                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2650                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2651                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2652                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2653                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2654                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2655                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2656                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2657                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2658                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2659                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2660                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2661                 {
2662                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2663                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2664                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2665                 }
2666                 else
2667                 {
2668                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2669                 }
2670 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2671 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2672                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2673                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2674                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2675                 {
2676                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2677                         if (rsurface.rtlight)
2678                         {
2679                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2680                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2681                         }
2682                 }
2683 #endif
2684                 break;
2685         case RENDERPATH_D3D10:
2686                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2687                 break;
2688         case RENDERPATH_D3D11:
2689                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2690                 break;
2691         case RENDERPATH_GL20:
2692         case RENDERPATH_GLES2:
2693                 if (!vid.useinterleavedarrays)
2694                 {
2695                         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);
2696                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2697                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2700                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2701                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2702                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2703                 }
2704                 else
2705                 {
2706                         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);
2707                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2708                 }
2709                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2710                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2711                 if (mode == SHADERMODE_LIGHTSOURCE)
2712                 {
2713                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2714                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2715                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2716                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2717                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2718                         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);
2719         
2720                         // additive passes are only darkened by fog, not tinted
2721                         if (r_glsl_permutation->loc_FogColor >= 0)
2722                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2723                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2724                 }
2725                 else
2726                 {
2727                         if (mode == SHADERMODE_FLATCOLOR)
2728                         {
2729                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2730                         }
2731                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2732                         {
2733                                 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]);
2734                                 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]);
2735                                 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);
2736                                 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);
2737                                 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);
2738                                 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]);
2739                                 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]);
2740                         }
2741                         else
2742                         {
2743                                 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]);
2744                                 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]);
2745                                 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);
2746                                 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);
2747                                 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);
2748                         }
2749                         // additive passes are only darkened by fog, not tinted
2750                         if (r_glsl_permutation->loc_FogColor >= 0)
2751                         {
2752                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2753                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2754                                 else
2755                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2756                         }
2757                         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);
2758                         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]);
2759                         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]);
2760                         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]);
2761                         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]);
2762                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2763                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2764                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2765                         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]);
2766                 }
2767                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2768                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2769                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2770                 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]);
2771                 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]);
2772
2773                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2774                 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));
2775                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2776                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2777                 {
2778                         if (rsurface.texture->pantstexture)
2779                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2780                         else
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2782                 }
2783                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2784                 {
2785                         if (rsurface.texture->shirttexture)
2786                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2787                         else
2788                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2789                 }
2790                 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]);
2791                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2792                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2793                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2794                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2795                 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]);
2796                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797                 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);}
2798                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2799
2800                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2802                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2803                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2805                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2806                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2811                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2812                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2813                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2814                 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);
2815                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2816                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2817                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2818                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2819                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2820                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2821                 {
2822                         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);
2823                         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);
2824                         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);
2825                 }
2826                 else
2827                 {
2828                         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);
2829                 }
2830                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2831                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2832                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2833                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2834                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2835                 {
2836                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2837                         if (rsurface.rtlight)
2838                         {
2839                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2840                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2841                         }
2842                 }
2843                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2844                 CHECKGLERROR
2845                 break;
2846         case RENDERPATH_GL13:
2847         case RENDERPATH_GL11:
2848                 break;
2849         case RENDERPATH_SOFT:
2850                 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);
2851                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2852                 R_SetupShader_SetPermutationSoft(mode, permutation);
2853                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2854                 if (mode == SHADERMODE_LIGHTSOURCE)
2855                 {
2856                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2862         
2863                         // additive passes are only darkened by fog, not tinted
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2865                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2866                 }
2867                 else
2868                 {
2869                         if (mode == SHADERMODE_FLATCOLOR)
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2872                         }
2873                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2874                         {
2875                                 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]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2877                                 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);
2878                                 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);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2880                                 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]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2882                         }
2883                         else
2884                         {
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2887                                 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);
2888                                 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);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2890                         }
2891                         // additive passes are only darkened by fog, not tinted
2892                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2894                         else
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2896                         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);
2897                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2898                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2899                         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]);
2900                         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]);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2904                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2905                 }
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2908                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2910                 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]);
2911
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2913                 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));
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916                 {
2917                         if (rsurface.texture->pantstexture)
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2919                         else
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921                 }
2922                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923                 {
2924                         if (rsurface.texture->shirttexture)
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2926                         else
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928                 }
2929                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2934                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2935                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2936
2937                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2938                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2939                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2940                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2941                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2942                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2943                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2944                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2945                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2946                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2947                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2948                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2949                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2950                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2951                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2952                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2953                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2954                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2955                 {
2956                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2957                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2958                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2959                 }
2960                 else
2961                 {
2962                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2963                 }
2964 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2965 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2966                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2967                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2968                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2969                 {
2970                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2971                         if (rsurface.rtlight)
2972                         {
2973                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2974                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2975                         }
2976                 }
2977                 break;
2978         }
2979 }
2980
2981 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2982 {
2983         // select a permutation of the lighting shader appropriate to this
2984         // combination of texture, entity, light source, and fogging, only use the
2985         // minimum features necessary to avoid wasting rendering time in the
2986         // fragment shader on features that are not being used
2987         unsigned int permutation = 0;
2988         unsigned int mode = 0;
2989         const float *lightcolorbase = rtlight->currentcolor;
2990         float ambientscale = rtlight->ambientscale;
2991         float diffusescale = rtlight->diffusescale;
2992         float specularscale = rtlight->specularscale;
2993         // this is the location of the light in view space
2994         vec3_t viewlightorigin;
2995         // this transforms from view space (camera) to light space (cubemap)
2996         matrix4x4_t viewtolight;
2997         matrix4x4_t lighttoview;
2998         float viewtolight16f[16];
2999         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3000         // light source
3001         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3002         if (rtlight->currentcubemap != r_texture_whitecube)
3003                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3004         if (diffusescale > 0)
3005                 permutation |= SHADERPERMUTATION_DIFFUSE;
3006         if (specularscale > 0)
3007                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3008         if (r_shadow_usingshadowmap2d)
3009         {
3010                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3011                 if (r_shadow_shadowmapvsdct)
3012                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3013
3014                 if (r_shadow_shadowmapsampler)
3015                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3016                 if (r_shadow_shadowmappcf > 1)
3017                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3018                 else if (r_shadow_shadowmappcf)
3019                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3020         }
3021         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3022         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3023         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3024         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3025         switch(vid.renderpath)
3026         {
3027         case RENDERPATH_D3D9:
3028 #ifdef SUPPORTD3D
3029                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3030                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3031                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3032                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3035                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3036                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3037                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3038                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3039                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3040
3041                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3042                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3043                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3044                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3045                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3046                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3047 #endif
3048                 break;
3049         case RENDERPATH_D3D10:
3050                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3051                 break;
3052         case RENDERPATH_D3D11:
3053                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054                 break;
3055         case RENDERPATH_GL20:
3056         case RENDERPATH_GLES2:
3057                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3058                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3059                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3060                 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);
3061                 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);
3062                 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);
3063                 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]);
3064                 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]);
3065                 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));
3066                 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]);
3067                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3068
3069                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3070                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3071                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3073                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3074                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3075                 break;
3076         case RENDERPATH_GL13:
3077         case RENDERPATH_GL11:
3078                 break;
3079         case RENDERPATH_SOFT:
3080                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3081                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3082                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3086                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3087                 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]);
3088                 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));
3089                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3090                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3091
3092                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3093                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3094                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3095                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3096                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3097                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3098                 break;
3099         }
3100 }
3101
3102 #define SKINFRAME_HASH 1024
3103
3104 typedef struct
3105 {
3106         int loadsequence; // incremented each level change
3107         memexpandablearray_t array;
3108         skinframe_t *hash[SKINFRAME_HASH];
3109 }
3110 r_skinframe_t;
3111 r_skinframe_t r_skinframe;
3112
3113 void R_SkinFrame_PrepareForPurge(void)
3114 {
3115         r_skinframe.loadsequence++;
3116         // wrap it without hitting zero
3117         if (r_skinframe.loadsequence >= 200)
3118                 r_skinframe.loadsequence = 1;
3119 }
3120
3121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3122 {
3123         if (!skinframe)
3124                 return;
3125         // mark the skinframe as used for the purging code
3126         skinframe->loadsequence = r_skinframe.loadsequence;
3127 }
3128
3129 void R_SkinFrame_Purge(void)
3130 {
3131         int i;
3132         skinframe_t *s;
3133         for (i = 0;i < SKINFRAME_HASH;i++)
3134         {
3135                 for (s = r_skinframe.hash[i];s;s = s->next)
3136                 {
3137                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3138                         {
3139                                 if (s->merged == s->base)
3140                                         s->merged = NULL;
3141                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3142                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3143                                 R_PurgeTexture(s->merged);s->merged = NULL;
3144                                 R_PurgeTexture(s->base  );s->base   = NULL;
3145                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3146                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3147                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3148                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3149                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3150                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3151                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3152                                 s->loadsequence = 0;
3153                         }
3154                 }
3155         }
3156 }
3157
3158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3159         skinframe_t *item;
3160         char basename[MAX_QPATH];
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         if( last == NULL ) {
3165                 int hashindex;
3166                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167                 item = r_skinframe.hash[hashindex];
3168         } else {
3169                 item = last->next;
3170         }
3171
3172         // linearly search through the hash bucket
3173         for( ; item ; item = item->next ) {
3174                 if( !strcmp( item->basename, basename ) ) {
3175                         return item;
3176                 }
3177         }
3178         return NULL;
3179 }
3180
3181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3182 {
3183         skinframe_t *item;
3184         int hashindex;
3185         char basename[MAX_QPATH];
3186
3187         Image_StripImageExtension(name, basename, sizeof(basename));
3188
3189         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3190         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3191                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3192                         break;
3193
3194         if (!item) {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 dyntexture = CL_GetDynTexture( basename );
3198                 if (!add && !dyntexture)
3199                         return NULL;
3200                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3201                 memset(item, 0, sizeof(*item));
3202                 strlcpy(item->basename, basename, sizeof(item->basename));
3203                 item->base = dyntexture; // either NULL or dyntexture handle
3204                 item->textureflags = textureflags;
3205                 item->comparewidth = comparewidth;
3206                 item->compareheight = compareheight;
3207                 item->comparecrc = comparecrc;
3208                 item->next = r_skinframe.hash[hashindex];
3209                 r_skinframe.hash[hashindex] = item;
3210         }
3211         else if( item->base == NULL )
3212         {
3213                 rtexture_t *dyntexture;
3214                 // check whether its a dynamic texture
3215                 // 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]
3216                 dyntexture = CL_GetDynTexture( basename );
3217                 item->base = dyntexture; // either NULL or dyntexture handle
3218         }
3219
3220         R_SkinFrame_MarkUsed(item);
3221         return item;
3222 }
3223
3224 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3225         { \
3226                 unsigned long long avgcolor[5], wsum; \
3227                 int pix, comp, w; \
3228                 avgcolor[0] = 0; \
3229                 avgcolor[1] = 0; \
3230                 avgcolor[2] = 0; \
3231                 avgcolor[3] = 0; \
3232                 avgcolor[4] = 0; \
3233                 wsum = 0; \
3234                 for(pix = 0; pix < cnt; ++pix) \
3235                 { \
3236                         w = 0; \
3237                         for(comp = 0; comp < 3; ++comp) \
3238                                 w += getpixel; \
3239                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3240                         { \
3241                                 ++wsum; \
3242                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3243                                 w = getpixel; \
3244                                 for(comp = 0; comp < 3; ++comp) \
3245                                         avgcolor[comp] += getpixel * w; \
3246                                 avgcolor[3] += w; \
3247                         } \
3248                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3249                         avgcolor[4] += getpixel; \
3250                 } \
3251                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3252                         avgcolor[3] = 1; \
3253                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3254                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3255                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3256                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3257         }
3258
3259 extern cvar_t gl_picmip;
3260 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3261 {
3262         int j;
3263         unsigned char *pixels;
3264         unsigned char *bumppixels;
3265         unsigned char *basepixels = NULL;
3266         int basepixels_width = 0;
3267         int basepixels_height = 0;
3268         skinframe_t *skinframe;
3269         rtexture_t *ddsbase = NULL;
3270         qboolean ddshasalpha = false;
3271         float ddsavgcolor[4];
3272         char basename[MAX_QPATH];
3273         int miplevel = R_PicmipForFlags(textureflags);
3274         int savemiplevel = miplevel;
3275         int mymiplevel;
3276
3277         if (cls.state == ca_dedicated)
3278                 return NULL;
3279
3280         // return an existing skinframe if already loaded
3281         // if loading of the first image fails, don't make a new skinframe as it
3282         // would cause all future lookups of this to be missing
3283         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3284         if (skinframe && skinframe->base)
3285                 return skinframe;
3286
3287         Image_StripImageExtension(name, basename, sizeof(basename));
3288
3289         // check for DDS texture file first
3290         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3291         {
3292                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3293                 if (basepixels == NULL)
3294                         return NULL;
3295         }
3296
3297         // FIXME handle miplevel
3298
3299         if (developer_loading.integer)
3300                 Con_Printf("loading skin \"%s\"\n", name);
3301
3302         // we've got some pixels to store, so really allocate this new texture now
3303         if (!skinframe)
3304                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3305         skinframe->stain = NULL;
3306         skinframe->merged = NULL;
3307         skinframe->base = NULL;
3308         skinframe->pants = NULL;
3309         skinframe->shirt = NULL;
3310         skinframe->nmap = NULL;
3311         skinframe->gloss = NULL;
3312         skinframe->glow = NULL;
3313         skinframe->fog = NULL;
3314         skinframe->reflect = NULL;
3315         skinframe->hasalpha = false;
3316
3317         if (ddsbase)
3318         {
3319                 skinframe->base = ddsbase;
3320                 skinframe->hasalpha = ddshasalpha;
3321                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3322                 if (r_loadfog && skinframe->hasalpha)
3323                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3324                 //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]);
3325         }
3326         else
3327         {
3328                 basepixels_width = image_width;
3329                 basepixels_height = image_height;
3330                 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);
3331                 if (textureflags & TEXF_ALPHA)
3332                 {
3333                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3334                         {
3335                                 if (basepixels[j] < 255)
3336                                 {
3337                                         skinframe->hasalpha = true;
3338                                         break;
3339                                 }
3340                         }
3341                         if (r_loadfog && skinframe->hasalpha)
3342                         {
3343                                 // has transparent pixels
3344                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3345                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3346                                 {
3347                                         pixels[j+0] = 255;
3348                                         pixels[j+1] = 255;
3349                                         pixels[j+2] = 255;
3350                                         pixels[j+3] = basepixels[j+3];
3351                                 }
3352                                 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);
3353                                 Mem_Free(pixels);
3354                         }
3355                 }
3356                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3357                 //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]);
3358                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3359                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3360                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3361                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3362         }
3363
3364         if (r_loaddds)
3365         {
3366                 mymiplevel = savemiplevel;
3367                 if (r_loadnormalmap)
3368                         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);
3369                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3370                 if (r_loadgloss)
3371                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3372                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3373                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3374                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3375         }
3376
3377         // _norm is the name used by tenebrae and has been adopted as standard
3378         if (r_loadnormalmap && skinframe->nmap == NULL)
3379         {
3380                 mymiplevel = savemiplevel;
3381                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3382                 {
3383                         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);
3384                         Mem_Free(pixels);
3385                         pixels = NULL;
3386                 }
3387                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3388                 {
3389                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3390                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3391                         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);
3392                         Mem_Free(pixels);
3393                         Mem_Free(bumppixels);
3394                 }
3395                 else if (r_shadow_bumpscale_basetexture.value > 0)
3396                 {
3397                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3398                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3399                         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);
3400                         Mem_Free(pixels);
3401                 }
3402                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3403                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3404         }
3405
3406         // _luma is supported only for tenebrae compatibility
3407         // _glow is the preferred name
3408         mymiplevel = savemiplevel;
3409         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))))
3410         {
3411                 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);
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3413                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3414                 Mem_Free(pixels);pixels = NULL;
3415         }
3416
3417         mymiplevel = savemiplevel;
3418         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3419         {
3420                 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);
3421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3422                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3423                 Mem_Free(pixels);
3424                 pixels = NULL;
3425         }
3426
3427         mymiplevel = savemiplevel;
3428         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3429         {
3430                 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);
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3432                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3433                 Mem_Free(pixels);
3434                 pixels = NULL;
3435         }
3436
3437         mymiplevel = savemiplevel;
3438         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3439         {
3440                 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);
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3442                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3443                 Mem_Free(pixels);
3444                 pixels = NULL;
3445         }
3446
3447         mymiplevel = savemiplevel;
3448         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3449         {
3450                 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);
3451                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3452                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3453                 Mem_Free(pixels);
3454                 pixels = NULL;
3455         }
3456
3457         if (basepixels)
3458                 Mem_Free(basepixels);
3459
3460         return skinframe;
3461 }
3462
3463 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3464 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3465 {
3466         int i;
3467         unsigned char *temp1, *temp2;
3468         skinframe_t *skinframe;
3469
3470         if (cls.state == ca_dedicated)
3471                 return NULL;
3472
3473         // if already loaded just return it, otherwise make a new skinframe
3474         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3475         if (skinframe && skinframe->base)
3476                 return skinframe;
3477
3478         skinframe->stain = NULL;
3479         skinframe->merged = NULL;
3480         skinframe->base = NULL;
3481         skinframe->pants = NULL;
3482         skinframe->shirt = NULL;
3483         skinframe->nmap = NULL;
3484         skinframe->gloss = NULL;
3485         skinframe->glow = NULL;
3486         skinframe->fog = NULL;
3487         skinframe->reflect = NULL;
3488         skinframe->hasalpha = false;
3489
3490         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3491         if (!skindata)
3492                 return NULL;
3493
3494         if (developer_loading.integer)
3495                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3496
3497         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3498         {
3499                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3500                 temp2 = temp1 + width * height * 4;
3501                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3502                 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);
3503                 Mem_Free(temp1);
3504         }
3505         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3506         if (textureflags & TEXF_ALPHA)
3507         {
3508                 for (i = 3;i < width * height * 4;i += 4)
3509                 {
3510                         if (skindata[i] < 255)
3511                         {
3512                                 skinframe->hasalpha = true;
3513                                 break;
3514                         }
3515                 }
3516                 if (r_loadfog && skinframe->hasalpha)
3517                 {
3518                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3519                         memcpy(fogpixels, skindata, width * height * 4);
3520                         for (i = 0;i < width * height * 4;i += 4)
3521                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3522                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3523                         Mem_Free(fogpixels);
3524                 }
3525         }
3526
3527         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3528         //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]);
3529
3530         return skinframe;
3531 }
3532
3533 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3534 {
3535         int i;
3536         int featuresmask;
3537         skinframe_t *skinframe;
3538
3539         if (cls.state == ca_dedicated)
3540                 return NULL;
3541
3542         // if already loaded just return it, otherwise make a new skinframe
3543         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3544         if (skinframe && skinframe->base)
3545                 return skinframe;
3546
3547         skinframe->stain = NULL;
3548         skinframe->merged = NULL;
3549         skinframe->base = NULL;
3550         skinframe->pants = NULL;
3551         skinframe->shirt = NULL;
3552         skinframe->nmap = NULL;
3553         skinframe->gloss = NULL;
3554         skinframe->glow = NULL;
3555         skinframe->fog = NULL;
3556         skinframe->reflect = NULL;
3557         skinframe->hasalpha = false;
3558
3559         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3560         if (!skindata)
3561                 return NULL;
3562
3563         if (developer_loading.integer)
3564                 Con_Printf("loading quake skin \"%s\"\n", name);
3565
3566         // 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)
3567         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3568         memcpy(skinframe->qpixels, skindata, width*height);
3569         skinframe->qwidth = width;
3570         skinframe->qheight = height;
3571
3572         featuresmask = 0;
3573         for (i = 0;i < width * height;i++)
3574                 featuresmask |= palette_featureflags[skindata[i]];
3575
3576         skinframe->hasalpha = false;
3577         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3578         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3579         skinframe->qgeneratemerged = true;
3580         skinframe->qgeneratebase = skinframe->qhascolormapping;
3581         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3582
3583         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3584         //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]);
3585
3586         return skinframe;
3587 }
3588
3589 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3590 {
3591         int width;
3592         int height;
3593         unsigned char *skindata;
3594
3595         if (!skinframe->qpixels)
3596                 return;
3597
3598         if (!skinframe->qhascolormapping)
3599                 colormapped = false;
3600
3601         if (colormapped)
3602         {
3603                 if (!skinframe->qgeneratebase)
3604                         return;
3605         }
3606         else
3607         {
3608                 if (!skinframe->qgeneratemerged)
3609                         return;
3610         }
3611
3612         width = skinframe->qwidth;
3613         height = skinframe->qheight;
3614         skindata = skinframe->qpixels;
3615
3616         if (skinframe->qgeneratenmap)
3617         {
3618                 unsigned char *temp1, *temp2;
3619                 skinframe->qgeneratenmap = false;
3620                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3621                 temp2 = temp1 + width * height * 4;
3622                 // use either a custom palette or the quake palette
3623                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3624                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3625                 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);
3626                 Mem_Free(temp1);
3627         }
3628
3629         if (skinframe->qgenerateglow)
3630         {
3631                 skinframe->qgenerateglow = false;
3632                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3633         }
3634
3635         if (colormapped)
3636         {
3637                 skinframe->qgeneratebase = false;
3638                 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);
3639                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3640                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3641         }
3642         else
3643         {
3644                 skinframe->qgeneratemerged = false;
3645                 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);
3646         }
3647
3648         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3649         {
3650                 Mem_Free(skinframe->qpixels);
3651                 skinframe->qpixels = NULL;
3652         }
3653 }
3654
3655 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)
3656 {
3657         int i;
3658         skinframe_t *skinframe;
3659
3660         if (cls.state == ca_dedicated)
3661                 return NULL;
3662
3663         // if already loaded just return it, otherwise make a new skinframe
3664         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3665         if (skinframe && skinframe->base)
3666                 return skinframe;
3667
3668         skinframe->stain = NULL;
3669         skinframe->merged = NULL;
3670         skinframe->base = NULL;
3671         skinframe->pants = NULL;
3672         skinframe->shirt = NULL;
3673         skinframe->nmap = NULL;
3674         skinframe->gloss = NULL;
3675         skinframe->glow = NULL;
3676         skinframe->fog = NULL;
3677         skinframe->reflect = NULL;
3678         skinframe->hasalpha = false;
3679
3680         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3681         if (!skindata)
3682                 return NULL;
3683
3684         if (developer_loading.integer)
3685                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3686
3687         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3688         if (textureflags & TEXF_ALPHA)
3689         {
3690                 for (i = 0;i < width * height;i++)
3691                 {
3692                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3693                         {
3694                                 skinframe->hasalpha = true;
3695                                 break;
3696                         }
3697                 }
3698                 if (r_loadfog && skinframe->hasalpha)
3699                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3700         }
3701
3702         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3703         //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]);
3704
3705         return skinframe;
3706 }
3707
3708 skinframe_t *R_SkinFrame_LoadMissing(void)
3709 {
3710         skinframe_t *skinframe;
3711
3712         if (cls.state == ca_dedicated)
3713                 return NULL;
3714
3715         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3716         skinframe->stain = NULL;
3717         skinframe->merged = NULL;
3718         skinframe->base = NULL;
3719         skinframe->pants = NULL;
3720         skinframe->shirt = NULL;
3721         skinframe->nmap = NULL;
3722         skinframe->gloss = NULL;
3723         skinframe->glow = NULL;
3724         skinframe->fog = NULL;
3725         skinframe->reflect = NULL;
3726         skinframe->hasalpha = false;
3727
3728         skinframe->avgcolor[0] = rand() / RAND_MAX;
3729         skinframe->avgcolor[1] = rand() / RAND_MAX;
3730         skinframe->avgcolor[2] = rand() / RAND_MAX;
3731         skinframe->avgcolor[3] = 1;
3732
3733         return skinframe;
3734 }
3735
3736 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3737 typedef struct suffixinfo_s
3738 {
3739         const char *suffix;
3740         qboolean flipx, flipy, flipdiagonal;
3741 }
3742 suffixinfo_t;
3743 static suffixinfo_t suffix[3][6] =
3744 {
3745         {
3746                 {"px",   false, false, false},
3747                 {"nx",   false, false, false},
3748                 {"py",   false, false, false},
3749                 {"ny",   false, false, false},
3750                 {"pz",   false, false, false},
3751                 {"nz",   false, false, false}
3752         },
3753         {
3754                 {"posx", false, false, false},
3755                 {"negx", false, false, false},
3756                 {"posy", false, false, false},
3757                 {"negy", false, false, false},
3758                 {"posz", false, false, false},
3759                 {"negz", false, false, false}
3760         },
3761         {
3762                 {"rt",    true, false,  true},
3763                 {"lf",   false,  true,  true},
3764                 {"ft",    true,  true, false},
3765                 {"bk",   false, false, false},
3766                 {"up",    true, false,  true},
3767                 {"dn",    true, false,  true}
3768         }
3769 };
3770
3771 static int componentorder[4] = {0, 1, 2, 3};
3772
3773 rtexture_t *R_LoadCubemap(const char *basename)
3774 {
3775         int i, j, cubemapsize;
3776         unsigned char *cubemappixels, *image_buffer;
3777         rtexture_t *cubemaptexture;
3778         char name[256];
3779         // must start 0 so the first loadimagepixels has no requested width/height
3780         cubemapsize = 0;
3781         cubemappixels = NULL;
3782         cubemaptexture = NULL;
3783         // keep trying different suffix groups (posx, px, rt) until one loads
3784         for (j = 0;j < 3 && !cubemappixels;j++)
3785         {
3786                 // load the 6 images in the suffix group
3787                 for (i = 0;i < 6;i++)
3788                 {
3789                         // generate an image name based on the base and and suffix
3790                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3791                         // load it
3792                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3793                         {
3794                                 // an image loaded, make sure width and height are equal
3795                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3796                                 {
3797                                         // if this is the first image to load successfully, allocate the cubemap memory
3798                                         if (!cubemappixels && image_width >= 1)
3799                                         {
3800                                                 cubemapsize = image_width;
3801                                                 // note this clears to black, so unavailable sides are black
3802                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3803                                         }
3804                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3805                                         if (cubemappixels)
3806                                                 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);
3807                                 }
3808                                 else
3809                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3810                                 // free the image
3811                                 Mem_Free(image_buffer);
3812                         }
3813                 }
3814         }
3815         // if a cubemap loaded, upload it
3816         if (cubemappixels)
3817         {
3818                 if (developer_loading.integer)
3819                         Con_Printf("loading cubemap \"%s\"\n", basename);
3820
3821                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3822                 Mem_Free(cubemappixels);
3823         }
3824         else
3825         {
3826                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3827                 if (developer_loading.integer)
3828                 {
3829                         Con_Printf("(tried tried images ");
3830                         for (j = 0;j < 3;j++)
3831                                 for (i = 0;i < 6;i++)
3832                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3833                         Con_Print(" and was unable to find any of them).\n");
3834                 }
3835         }
3836         return cubemaptexture;
3837 }
3838
3839 rtexture_t *R_GetCubemap(const char *basename)
3840 {
3841         int i;
3842         for (i = 0;i < r_texture_numcubemaps;i++)
3843                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3844                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3845         if (i >= MAX_CUBEMAPS)
3846                 return r_texture_whitecube;
3847         r_texture_numcubemaps++;
3848         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3849         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3850         return r_texture_cubemaps[i].texture;
3851 }
3852
3853 void R_FreeCubemaps(void)
3854 {
3855         int i;
3856         for (i = 0;i < r_texture_numcubemaps;i++)
3857         {
3858                 if (developer_loading.integer)
3859                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3860                 if (r_texture_cubemaps[i].texture)
3861                         R_FreeTexture(r_texture_cubemaps[i].texture);
3862         }
3863         r_texture_numcubemaps = 0;
3864 }
3865
3866 void R_Main_FreeViewCache(void)
3867 {
3868         if (r_refdef.viewcache.entityvisible)
3869                 Mem_Free(r_refdef.viewcache.entityvisible);
3870         if (r_refdef.viewcache.world_pvsbits)
3871                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3872         if (r_refdef.viewcache.world_leafvisible)
3873                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3874         if (r_refdef.viewcache.world_surfacevisible)
3875                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3876         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3877 }
3878
3879 void R_Main_ResizeViewCache(void)
3880 {
3881         int numentities = r_refdef.scene.numentities;
3882         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3883         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3884         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3885         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3886         if (r_refdef.viewcache.maxentities < numentities)
3887         {
3888                 r_refdef.viewcache.maxentities = numentities;
3889                 if (r_refdef.viewcache.entityvisible)
3890                         Mem_Free(r_refdef.viewcache.entityvisible);
3891                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3892         }
3893         if (r_refdef.viewcache.world_numclusters != numclusters)
3894         {
3895                 r_refdef.viewcache.world_numclusters = numclusters;
3896                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3897                 if (r_refdef.viewcache.world_pvsbits)
3898                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3899                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3900         }
3901         if (r_refdef.viewcache.world_numleafs != numleafs)
3902         {
3903                 r_refdef.viewcache.world_numleafs = numleafs;
3904                 if (r_refdef.viewcache.world_leafvisible)
3905                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3906                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3907         }
3908         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3909         {
3910                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3911                 if (r_refdef.viewcache.world_surfacevisible)
3912                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3913                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3914         }
3915 }
3916
3917 extern rtexture_t *loadingscreentexture;
3918 void gl_main_start(void)
3919 {
3920         loadingscreentexture = NULL;
3921         r_texture_blanknormalmap = NULL;
3922         r_texture_white = NULL;
3923         r_texture_grey128 = NULL;
3924         r_texture_black = NULL;
3925         r_texture_whitecube = NULL;
3926         r_texture_normalizationcube = NULL;
3927         r_texture_fogattenuation = NULL;
3928         r_texture_fogheighttexture = NULL;
3929         r_texture_gammaramps = NULL;
3930         r_texture_numcubemaps = 0;
3931
3932         r_loaddds = r_texture_dds_load.integer != 0;
3933         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3934
3935         switch(vid.renderpath)
3936         {
3937         case RENDERPATH_GL20:
3938         case RENDERPATH_D3D9:
3939         case RENDERPATH_D3D10:
3940         case RENDERPATH_D3D11:
3941         case RENDERPATH_SOFT:
3942                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3943                 Cvar_SetValueQuick(&gl_combine, 1);
3944                 Cvar_SetValueQuick(&r_glsl, 1);
3945                 r_loadnormalmap = true;
3946                 r_loadgloss = true;
3947                 r_loadfog = false;
3948                 break;
3949         case RENDERPATH_GL13:
3950                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3951                 Cvar_SetValueQuick(&gl_combine, 1);
3952                 Cvar_SetValueQuick(&r_glsl, 0);
3953                 r_loadnormalmap = false;
3954                 r_loadgloss = false;
3955                 r_loadfog = true;
3956                 break;
3957         case RENDERPATH_GL11:
3958                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3959                 Cvar_SetValueQuick(&gl_combine, 0);
3960                 Cvar_SetValueQuick(&r_glsl, 0);
3961                 r_loadnormalmap = false;
3962                 r_loadgloss = false;
3963                 r_loadfog = true;
3964                 break;
3965         case RENDERPATH_GLES2:
3966                 Cvar_SetValueQuick(&r_textureunits, 1);
3967                 Cvar_SetValueQuick(&gl_combine, 1);
3968                 Cvar_SetValueQuick(&r_glsl, 1);
3969                 r_loadnormalmap = true;
3970                 r_loadgloss = false;
3971                 r_loadfog = false;
3972                 break;
3973         }
3974
3975         R_AnimCache_Free();
3976         R_FrameData_Reset();
3977
3978         r_numqueries = 0;
3979         r_maxqueries = 0;
3980         memset(r_queries, 0, sizeof(r_queries));
3981
3982         r_qwskincache = NULL;
3983         r_qwskincache_size = 0;
3984
3985         // set up r_skinframe loading system for textures
3986         memset(&r_skinframe, 0, sizeof(r_skinframe));
3987         r_skinframe.loadsequence = 1;
3988         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3989
3990         r_main_texturepool = R_AllocTexturePool();
3991         R_BuildBlankTextures();
3992         R_BuildNoTexture();
3993         if (vid.support.arb_texture_cube_map)
3994         {
3995                 R_BuildWhiteCube();
3996                 R_BuildNormalizationCube();
3997         }
3998         r_texture_fogattenuation = NULL;
3999         r_texture_fogheighttexture = NULL;
4000         r_texture_gammaramps = NULL;
4001         //r_texture_fogintensity = NULL;
4002         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4003         memset(&r_waterstate, 0, sizeof(r_waterstate));
4004         r_glsl_permutation = NULL;
4005         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4006         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4007         glslshaderstring = NULL;
4008 #ifdef SUPPORTD3D
4009         r_hlsl_permutation = NULL;
4010         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4011         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4012 #endif
4013         hlslshaderstring = NULL;
4014         memset(&r_svbsp, 0, sizeof (r_svbsp));
4015
4016         r_refdef.fogmasktable_density = 0;
4017 }
4018
4019 void gl_main_shutdown(void)
4020 {
4021         R_AnimCache_Free();
4022         R_FrameData_Reset();
4023
4024         R_Main_FreeViewCache();
4025
4026         switch(vid.renderpath)
4027         {
4028         case RENDERPATH_GL11:
4029         case RENDERPATH_GL13:
4030         case RENDERPATH_GL20:
4031         case RENDERPATH_GLES2:
4032                 if (r_maxqueries)
4033                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4034                 break;
4035         case RENDERPATH_D3D9:
4036                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4037                 break;
4038         case RENDERPATH_D3D10:
4039                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4040                 break;
4041         case RENDERPATH_D3D11:
4042                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4043                 break;
4044         case RENDERPATH_SOFT:
4045                 break;
4046         }
4047
4048         r_numqueries = 0;
4049         r_maxqueries = 0;
4050         memset(r_queries, 0, sizeof(r_queries));
4051
4052         r_qwskincache = NULL;
4053         r_qwskincache_size = 0;
4054
4055         // clear out the r_skinframe state
4056         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4057         memset(&r_skinframe, 0, sizeof(r_skinframe));
4058
4059         if (r_svbsp.nodes)
4060                 Mem_Free(r_svbsp.nodes);
4061         memset(&r_svbsp, 0, sizeof (r_svbsp));
4062         R_FreeTexturePool(&r_main_texturepool);
4063         loadingscreentexture = NULL;
4064         r_texture_blanknormalmap = NULL;
4065         r_texture_white = NULL;
4066         r_texture_grey128 = NULL;
4067         r_texture_black = NULL;
4068         r_texture_whitecube = NULL;
4069         r_texture_normalizationcube = NULL;
4070         r_texture_fogattenuation = NULL;
4071         r_texture_fogheighttexture = NULL;
4072         r_texture_gammaramps = NULL;
4073         r_texture_numcubemaps = 0;
4074         //r_texture_fogintensity = NULL;
4075         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4076         memset(&r_waterstate, 0, sizeof(r_waterstate));
4077         R_GLSL_Restart_f();
4078
4079         r_glsl_permutation = NULL;
4080         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4081         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4082         glslshaderstring = NULL;
4083 #ifdef SUPPORTD3D
4084         r_hlsl_permutation = NULL;
4085         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4086         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4087 #endif
4088         hlslshaderstring = NULL;
4089 }
4090
4091 extern void CL_ParseEntityLump(char *entitystring);
4092 void gl_main_newmap(void)
4093 {
4094         // FIXME: move this code to client
4095         char *entities, entname[MAX_QPATH];
4096         if (r_qwskincache)
4097                 Mem_Free(r_qwskincache);
4098         r_qwskincache = NULL;
4099         r_qwskincache_size = 0;
4100         if (cl.worldmodel)
4101         {
4102                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4103                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4104                 {
4105                         CL_ParseEntityLump(entities);
4106                         Mem_Free(entities);
4107                         return;
4108                 }
4109                 if (cl.worldmodel->brush.entities)
4110                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4111         }
4112         R_Main_FreeViewCache();
4113
4114         R_FrameData_Reset();
4115 }
4116
4117 void GL_Main_Init(void)
4118 {
4119         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4120
4121         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4122         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4123         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4124         if (gamemode == GAME_NEHAHRA)
4125         {
4126                 Cvar_RegisterVariable (&gl_fogenable);
4127                 Cvar_RegisterVariable (&gl_fogdensity);
4128                 Cvar_RegisterVariable (&gl_fogred);
4129                 Cvar_RegisterVariable (&gl_foggreen);
4130                 Cvar_RegisterVariable (&gl_fogblue);
4131                 Cvar_RegisterVariable (&gl_fogstart);
4132                 Cvar_RegisterVariable (&gl_fogend);
4133                 Cvar_RegisterVariable (&gl_skyclip);
4134         }
4135         Cvar_RegisterVariable(&r_motionblur);
4136         Cvar_RegisterVariable(&r_motionblur_maxblur);
4137         Cvar_RegisterVariable(&r_motionblur_bmin);
4138         Cvar_RegisterVariable(&r_motionblur_vmin);
4139         Cvar_RegisterVariable(&r_motionblur_vmax);
4140         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4141         Cvar_RegisterVariable(&r_motionblur_randomize);
4142         Cvar_RegisterVariable(&r_damageblur);
4143         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4144         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4145         Cvar_RegisterVariable(&r_equalize_entities_by);
4146         Cvar_RegisterVariable(&r_equalize_entities_to);
4147         Cvar_RegisterVariable(&r_depthfirst);
4148         Cvar_RegisterVariable(&r_useinfinitefarclip);
4149         Cvar_RegisterVariable(&r_farclip_base);
4150         Cvar_RegisterVariable(&r_farclip_world);
4151         Cvar_RegisterVariable(&r_nearclip);
4152         Cvar_RegisterVariable(&r_showbboxes);
4153         Cvar_RegisterVariable(&r_showsurfaces);
4154         Cvar_RegisterVariable(&r_showtris);
4155         Cvar_RegisterVariable(&r_shownormals);
4156         Cvar_RegisterVariable(&r_showlighting);
4157         Cvar_RegisterVariable(&r_showshadowvolumes);
4158         Cvar_RegisterVariable(&r_showcollisionbrushes);
4159         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4160         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4161         Cvar_RegisterVariable(&r_showdisabledepthtest);
4162         Cvar_RegisterVariable(&r_drawportals);
4163         Cvar_RegisterVariable(&r_drawentities);
4164         Cvar_RegisterVariable(&r_draw2d);
4165         Cvar_RegisterVariable(&r_drawworld);
4166         Cvar_RegisterVariable(&r_cullentities_trace);
4167         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4168         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4169         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4170         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4171         Cvar_RegisterVariable(&r_drawviewmodel);
4172         Cvar_RegisterVariable(&r_drawexteriormodel);
4173         Cvar_RegisterVariable(&r_speeds);
4174         Cvar_RegisterVariable(&r_fullbrights);
4175         Cvar_RegisterVariable(&r_wateralpha);
4176         Cvar_RegisterVariable(&r_dynamic);
4177         Cvar_RegisterVariable(&r_fakelight);
4178         Cvar_RegisterVariable(&r_fakelight_intensity);
4179         Cvar_RegisterVariable(&r_fullbright);
4180         Cvar_RegisterVariable(&r_shadows);
4181         Cvar_RegisterVariable(&r_shadows_darken);
4182         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4183         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4184         Cvar_RegisterVariable(&r_shadows_throwdistance);
4185         Cvar_RegisterVariable(&r_shadows_throwdirection);
4186         Cvar_RegisterVariable(&r_shadows_focus);
4187         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4188         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4189         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4190         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4191         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4192         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4193         Cvar_RegisterVariable(&r_fog_exp2);
4194         Cvar_RegisterVariable(&r_drawfog);
4195         Cvar_RegisterVariable(&r_transparentdepthmasking);
4196         Cvar_RegisterVariable(&r_texture_dds_load);
4197         Cvar_RegisterVariable(&r_texture_dds_save);
4198         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4199         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4200         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4201         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4202         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4203         Cvar_RegisterVariable(&r_textureunits);
4204         Cvar_RegisterVariable(&gl_combine);
4205         Cvar_RegisterVariable(&r_glsl);
4206         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4207         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4208         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4209         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4210         Cvar_RegisterVariable(&r_glsl_postprocess);
4211         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4212         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4213         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4214         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4215         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4216         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4217         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4218         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4219
4220         Cvar_RegisterVariable(&r_water);
4221         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4222         Cvar_RegisterVariable(&r_water_clippingplanebias);
4223         Cvar_RegisterVariable(&r_water_refractdistort);
4224         Cvar_RegisterVariable(&r_water_reflectdistort);
4225         Cvar_RegisterVariable(&r_water_scissormode);
4226         Cvar_RegisterVariable(&r_lerpsprites);
4227         Cvar_RegisterVariable(&r_lerpmodels);
4228         Cvar_RegisterVariable(&r_lerplightstyles);
4229         Cvar_RegisterVariable(&r_waterscroll);
4230         Cvar_RegisterVariable(&r_bloom);
4231         Cvar_RegisterVariable(&r_bloom_colorscale);
4232         Cvar_RegisterVariable(&r_bloom_brighten);
4233         Cvar_RegisterVariable(&r_bloom_blur);
4234         Cvar_RegisterVariable(&r_bloom_resolution);
4235         Cvar_RegisterVariable(&r_bloom_colorexponent);
4236         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4237         Cvar_RegisterVariable(&r_hdr);
4238         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4239         Cvar_RegisterVariable(&r_hdr_glowintensity);
4240         Cvar_RegisterVariable(&r_hdr_range);
4241         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4242         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4243         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4244         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4245         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4246         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4247         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4248         Cvar_RegisterVariable(&developer_texturelogging);
4249         Cvar_RegisterVariable(&gl_lightmaps);
4250         Cvar_RegisterVariable(&r_test);
4251         Cvar_RegisterVariable(&r_glsl_saturation);
4252         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4253         Cvar_RegisterVariable(&r_framedatasize);
4254         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4255                 Cvar_SetValue("r_fullbrights", 0);
4256         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4257
4258         Cvar_RegisterVariable(&r_track_sprites);
4259         Cvar_RegisterVariable(&r_track_sprites_flags);
4260         Cvar_RegisterVariable(&r_track_sprites_scalew);
4261         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4262         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4263         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4264         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4265         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4266 }
4267
4268 extern void R_Textures_Init(void);
4269 extern void GL_Draw_Init(void);
4270 extern void GL_Main_Init(void);
4271 extern void R_Shadow_Init(void);
4272 extern void R_Sky_Init(void);
4273 extern void GL_Surf_Init(void);
4274 extern void R_Particles_Init(void);
4275 extern void R_Explosion_Init(void);
4276 extern void gl_backend_init(void);
4277 extern void Sbar_Init(void);
4278 extern void R_LightningBeams_Init(void);
4279 extern void Mod_RenderInit(void);
4280 extern void Font_Init(void);
4281
4282 void Render_Init(void)
4283 {
4284         gl_backend_init();
4285         R_Textures_Init();
4286         GL_Main_Init();
4287         Font_Init();
4288         GL_Draw_Init();
4289         R_Shadow_Init();
4290         R_Sky_Init();
4291         GL_Surf_Init();
4292         Sbar_Init();
4293         R_Particles_Init();
4294         R_Explosion_Init();
4295         R_LightningBeams_Init();
4296         Mod_RenderInit();
4297 }
4298
4299 /*
4300 ===============
4301 GL_Init
4302 ===============
4303 */
4304 extern char *ENGINE_EXTENSIONS;
4305 void GL_Init (void)
4306 {
4307         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4308         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4309         gl_version = (const char *)qglGetString(GL_VERSION);
4310         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4311
4312         if (!gl_extensions)
4313                 gl_extensions = "";
4314         if (!gl_platformextensions)
4315                 gl_platformextensions = "";
4316
4317         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4318         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4319         Con_Printf("GL_VERSION: %s\n", gl_version);
4320         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4321         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4322
4323         VID_CheckExtensions();
4324
4325         // LordHavoc: report supported extensions
4326         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4327
4328         // clear to black (loading plaque will be seen over this)
4329         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4330 }
4331
4332 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4333 {
4334         int i;
4335         mplane_t *p;
4336         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4337         {
4338                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4339                 if (i == 4)
4340                         continue;
4341                 p = r_refdef.view.frustum + i;
4342                 switch(p->signbits)
4343                 {
4344                 default:
4345                 case 0:
4346                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4347                                 return true;
4348                         break;
4349                 case 1:
4350                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4351                                 return true;
4352                         break;
4353                 case 2:
4354                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4355                                 return true;
4356                         break;
4357                 case 3:
4358                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4359                                 return true;
4360                         break;
4361                 case 4:
4362                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4363                                 return true;
4364                         break;
4365                 case 5:
4366                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4367                                 return true;
4368                         break;
4369                 case 6:
4370                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4371                                 return true;
4372                         break;
4373                 case 7:
4374                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4375                                 return true;
4376                         break;
4377                 }
4378         }
4379         return false;
4380 }
4381
4382 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4383 {
4384         int i;
4385         const mplane_t *p;
4386         for (i = 0;i < numplanes;i++)
4387         {
4388                 p = planes + i;
4389                 switch(p->signbits)
4390                 {
4391                 default:
4392                 case 0:
4393                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 1:
4397                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 case 2:
4401                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 case 3:
4405                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4406                                 return true;
4407                         break;
4408                 case 4:
4409                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4410                                 return true;
4411                         break;
4412                 case 5:
4413                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4414                                 return true;
4415                         break;
4416                 case 6:
4417                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4418                                 return true;
4419                         break;
4420                 case 7:
4421                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4422                                 return true;
4423                         break;
4424                 }
4425         }
4426         return false;
4427 }
4428
4429 //==================================================================================
4430
4431 // LordHavoc: this stores temporary data used within the same frame
4432
4433 typedef struct r_framedata_mem_s
4434 {
4435         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4436         size_t size; // how much usable space
4437         size_t current; // how much space in use
4438         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4439         size_t wantedsize; // how much space was allocated
4440         unsigned char *data; // start of real data (16byte aligned)
4441 }
4442 r_framedata_mem_t;
4443
4444 static r_framedata_mem_t *r_framedata_mem;
4445
4446 void R_FrameData_Reset(void)
4447 {
4448         while (r_framedata_mem)
4449         {
4450                 r_framedata_mem_t *next = r_framedata_mem->purge;
4451                 Mem_Free(r_framedata_mem);
4452                 r_framedata_mem = next;
4453         }
4454 }
4455
4456 void R_FrameData_Resize(void)
4457 {
4458         size_t wantedsize;
4459         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4460         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4461         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4462         {
4463                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4464                 newmem->wantedsize = wantedsize;
4465                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4466                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4467                 newmem->current = 0;
4468                 newmem->mark = 0;
4469                 newmem->purge = r_framedata_mem;
4470                 r_framedata_mem = newmem;
4471         }
4472 }
4473
4474 void R_FrameData_NewFrame(void)
4475 {
4476         R_FrameData_Resize();
4477         if (!r_framedata_mem)
4478                 return;
4479         // if we ran out of space on the last frame, free the old memory now
4480         while (r_framedata_mem->purge)
4481         {
4482                 // repeatedly remove the second item in the list, leaving only head
4483                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4484                 Mem_Free(r_framedata_mem->purge);
4485                 r_framedata_mem->purge = next;
4486         }
4487         // reset the current mem pointer
4488         r_framedata_mem->current = 0;
4489         r_framedata_mem->mark = 0;
4490 }
4491
4492 void *R_FrameData_Alloc(size_t size)
4493 {
4494         void *data;
4495
4496         // align to 16 byte boundary - the data pointer is already aligned, so we
4497         // only need to ensure the size of every allocation is also aligned
4498         size = (size + 15) & ~15;
4499
4500         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4501         {
4502                 // emergency - we ran out of space, allocate more memory
4503                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4504                 R_FrameData_Resize();
4505         }
4506
4507         data = r_framedata_mem->data + r_framedata_mem->current;
4508         r_framedata_mem->current += size;
4509
4510         // count the usage for stats
4511         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4512         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4513
4514         return (void *)data;
4515 }
4516
4517 void *R_FrameData_Store(size_t size, void *data)
4518 {
4519         void *d = R_FrameData_Alloc(size);
4520         if (d && data)
4521                 memcpy(d, data, size);
4522         return d;
4523 }
4524
4525 void R_FrameData_SetMark(void)
4526 {
4527         if (!r_framedata_mem)
4528                 return;
4529         r_framedata_mem->mark = r_framedata_mem->current;
4530 }
4531
4532 void R_FrameData_ReturnToMark(void)
4533 {
4534         if (!r_framedata_mem)
4535                 return;
4536         r_framedata_mem->current = r_framedata_mem->mark;
4537 }
4538
4539 //==================================================================================
4540
4541 // LordHavoc: animcache originally written by Echon, rewritten since then
4542
4543 /**
4544  * Animation cache prevents re-generating mesh data for an animated model
4545  * multiple times in one frame for lighting, shadowing, reflections, etc.
4546  */
4547
4548 void R_AnimCache_Free(void)
4549 {
4550 }
4551
4552 void R_AnimCache_ClearCache(void)
4553 {
4554         int i;
4555         entity_render_t *ent;
4556
4557         for (i = 0;i < r_refdef.scene.numentities;i++)
4558         {
4559                 ent = r_refdef.scene.entities[i];
4560                 ent->animcache_vertex3f = NULL;
4561                 ent->animcache_normal3f = NULL;
4562                 ent->animcache_svector3f = NULL;
4563                 ent->animcache_tvector3f = NULL;
4564                 ent->animcache_vertexmesh = NULL;
4565                 ent->animcache_vertex3fbuffer = NULL;
4566                 ent->animcache_vertexmeshbuffer = NULL;
4567         }
4568 }
4569
4570 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4571 {
4572         int i;
4573
4574         // check if we need the meshbuffers
4575         if (!vid.useinterleavedarrays)
4576                 return;
4577
4578         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4579                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4580         // TODO: upload vertex3f buffer?
4581         if (ent->animcache_vertexmesh)
4582         {
4583                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4584                 for (i = 0;i < numvertices;i++)
4585                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4586                 if (ent->animcache_svector3f)
4587                         for (i = 0;i < numvertices;i++)
4588                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4589                 if (ent->animcache_tvector3f)
4590                         for (i = 0;i < numvertices;i++)
4591                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4592                 if (ent->animcache_normal3f)
4593                         for (i = 0;i < numvertices;i++)
4594                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4595                 // TODO: upload vertexmeshbuffer?
4596         }
4597 }
4598
4599 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4600 {
4601         dp_model_t *model = ent->model;
4602         int numvertices;
4603         // see if it's already cached this frame
4604         if (ent->animcache_vertex3f)
4605         {
4606                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4607                 if (wantnormals || wanttangents)
4608                 {
4609                         if (ent->animcache_normal3f)
4610                                 wantnormals = false;
4611                         if (ent->animcache_svector3f)
4612                                 wanttangents = false;
4613                         if (wantnormals || wanttangents)
4614                         {
4615                                 numvertices = model->surfmesh.num_vertices;
4616                                 if (wantnormals)
4617                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4618                                 if (wanttangents)
4619                                 {
4620                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4621                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4622                                 }
4623                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4624                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4625                         }
4626                 }
4627         }
4628         else
4629         {
4630                 // see if this ent is worth caching
4631                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4632                         return false;
4633                 // get some memory for this entity and generate mesh data
4634                 numvertices = model->surfmesh.num_vertices;
4635                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4636                 if (wantnormals)
4637                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4638                 if (wanttangents)
4639                 {
4640                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4641                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4642                 }
4643                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4644                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4645         }
4646         return true;
4647 }
4648
4649 void R_AnimCache_CacheVisibleEntities(void)
4650 {
4651         int i;
4652         qboolean wantnormals = true;
4653         qboolean wanttangents = !r_showsurfaces.integer;
4654
4655         switch(vid.renderpath)
4656         {
4657         case RENDERPATH_GL20:
4658         case RENDERPATH_D3D9:
4659         case RENDERPATH_D3D10:
4660         case RENDERPATH_D3D11:
4661         case RENDERPATH_GLES2:
4662                 break;
4663         case RENDERPATH_GL13:
4664         case RENDERPATH_GL11:
4665                 wanttangents = false;
4666                 break;
4667         case RENDERPATH_SOFT:
4668                 break;
4669         }
4670
4671         if (r_shownormals.integer)
4672                 wanttangents = wantnormals = true;
4673
4674         // TODO: thread this
4675         // NOTE: R_PrepareRTLights() also caches entities
4676
4677         for (i = 0;i < r_refdef.scene.numentities;i++)
4678                 if (r_refdef.viewcache.entityvisible[i])
4679                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4680 }
4681
4682 //==================================================================================
4683
4684 static void R_View_UpdateEntityLighting (void)
4685 {
4686         int i;
4687         entity_render_t *ent;
4688         vec3_t tempdiffusenormal, avg;
4689         vec_t f, fa, fd, fdd;
4690         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4691
4692         for (i = 0;i < r_refdef.scene.numentities;i++)
4693         {
4694                 ent = r_refdef.scene.entities[i];
4695
4696                 // skip unseen models
4697                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4698                         continue;
4699
4700                 // skip bsp models
4701                 if (ent->model && ent->model->brush.num_leafs)
4702                 {
4703                         // TODO: use modellight for r_ambient settings on world?
4704                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4705                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4706                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4707                         continue;
4708                 }
4709
4710                 // fetch the lighting from the worldmodel data
4711                 VectorClear(ent->modellight_ambient);
4712                 VectorClear(ent->modellight_diffuse);
4713                 VectorClear(tempdiffusenormal);
4714                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4715                 {
4716                         vec3_t org;
4717                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4718
4719                         // complete lightning for lit sprites
4720                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4721                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4722                         {
4723                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4724                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4725                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4726                         }
4727                         else
4728                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4729
4730                         if(ent->flags & RENDER_EQUALIZE)
4731                         {
4732                                 // first fix up ambient lighting...
4733                                 if(r_equalize_entities_minambient.value > 0)
4734                                 {
4735                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4736                                         if(fd > 0)
4737                                         {
4738                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4739                                                 if(fa < r_equalize_entities_minambient.value * fd)
4740                                                 {
4741                                                         // solve:
4742                                                         //   fa'/fd' = minambient
4743                                                         //   fa'+0.25*fd' = fa+0.25*fd
4744                                                         //   ...
4745                                                         //   fa' = fd' * minambient
4746                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4747                                                         //   ...
4748                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4749                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4750                                                         //   ...
4751                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4752                                                         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
4753                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4754                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4755                                                 }
4756                                         }
4757                                 }
4758
4759                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4760                                 {
4761                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4762                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4763                                         f = fa + 0.25 * fd;
4764                                         if(f > 0)
4765                                         {
4766                                                 // adjust brightness and saturation to target
4767                                                 avg[0] = avg[1] = avg[2] = fa / f;
4768                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4769                                                 avg[0] = avg[1] = avg[2] = fd / f;
4770                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4771                                         }
4772                                 }
4773                         }
4774                 }
4775                 else // highly rare
4776                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4777
4778                 // move the light direction into modelspace coordinates for lighting code
4779                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4780                 if(VectorLength2(ent->modellight_lightdir) == 0)
4781                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4782                 VectorNormalize(ent->modellight_lightdir);
4783         }
4784 }
4785
4786 #define MAX_LINEOFSIGHTTRACES 64
4787
4788 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4789 {
4790         int i;
4791         vec3_t boxmins, boxmaxs;
4792         vec3_t start;
4793         vec3_t end;
4794         dp_model_t *model = r_refdef.scene.worldmodel;
4795
4796         if (!model || !model->brush.TraceLineOfSight)
4797                 return true;
4798
4799         // expand the box a little
4800         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4801         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4802         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4803         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4804         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4805         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4806
4807         // return true if eye is inside enlarged box
4808         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4809                 return true;
4810
4811         // try center
4812         VectorCopy(eye, start);
4813         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4814         if (model->brush.TraceLineOfSight(model, start, end))
4815                 return true;
4816
4817         // try various random positions
4818         for (i = 0;i < numsamples;i++)
4819         {
4820                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4821                 if (model->brush.TraceLineOfSight(model, start, end))
4822                         return true;
4823         }
4824
4825         return false;
4826 }
4827
4828
4829 static void R_View_UpdateEntityVisible (void)
4830 {
4831         int i;
4832         int renderimask;
4833         int samples;
4834         entity_render_t *ent;
4835
4836         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4837                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4838                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4839                 :                                                          RENDER_EXTERIORMODEL;
4840         if (!r_drawviewmodel.integer)
4841                 renderimask |= RENDER_VIEWMODEL;
4842         if (!r_drawexteriormodel.integer)
4843                 renderimask |= RENDER_EXTERIORMODEL;
4844         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4845         {
4846                 // worldmodel can check visibility
4847                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4848                 for (i = 0;i < r_refdef.scene.numentities;i++)
4849                 {
4850                         ent = r_refdef.scene.entities[i];
4851                         if (!(ent->flags & renderimask))
4852                         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)))
4853                         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))
4854                                 r_refdef.viewcache.entityvisible[i] = true;
4855                 }
4856                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4857                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4858                 {
4859                         for (i = 0;i < r_refdef.scene.numentities;i++)
4860                         {
4861                                 ent = r_refdef.scene.entities[i];
4862                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4863                                 {
4864                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4865                                         if (samples < 0)
4866                                                 continue; // temp entities do pvs only
4867                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4868                                                 ent->last_trace_visibility = realtime;
4869                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4870                                                 r_refdef.viewcache.entityvisible[i] = 0;
4871                                 }
4872                         }
4873                 }
4874         }
4875         else
4876         {
4877                 // no worldmodel or it can't check visibility
4878                 for (i = 0;i < r_refdef.scene.numentities;i++)
4879                 {
4880                         ent = r_refdef.scene.entities[i];
4881                         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));
4882                 }
4883         }
4884 }
4885
4886 /// only used if skyrendermasked, and normally returns false
4887 int R_DrawBrushModelsSky (void)
4888 {
4889         int i, sky;
4890         entity_render_t *ent;
4891
4892         sky = false;
4893         for (i = 0;i < r_refdef.scene.numentities;i++)
4894         {
4895                 if (!r_refdef.viewcache.entityvisible[i])
4896                         continue;
4897                 ent = r_refdef.scene.entities[i];
4898                 if (!ent->model || !ent->model->DrawSky)
4899                         continue;
4900                 ent->model->DrawSky(ent);
4901                 sky = true;
4902         }
4903         return sky;
4904 }
4905
4906 static void R_DrawNoModel(entity_render_t *ent);
4907 static void R_DrawModels(void)
4908 {
4909         int i;
4910         entity_render_t *ent;
4911
4912         for (i = 0;i < r_refdef.scene.numentities;i++)
4913         {
4914                 if (!r_refdef.viewcache.entityvisible[i])
4915                         continue;
4916                 ent = r_refdef.scene.entities[i];
4917                 r_refdef.stats.entities++;
4918                 if (ent->model && ent->model->Draw != NULL)
4919                         ent->model->Draw(ent);
4920                 else
4921                         R_DrawNoModel(ent);
4922         }
4923 }
4924
4925 static void R_DrawModelsDepth(void)
4926 {
4927         int i;
4928         entity_render_t *ent;
4929
4930         for (i = 0;i < r_refdef.scene.numentities;i++)
4931         {
4932                 if (!r_refdef.viewcache.entityvisible[i])
4933                         continue;
4934                 ent = r_refdef.scene.entities[i];
4935                 if (ent->model && ent->model->DrawDepth != NULL)
4936                         ent->model->DrawDepth(ent);
4937         }
4938 }
4939
4940 static void R_DrawModelsDebug(void)
4941 {
4942         int i;
4943         entity_render_t *ent;
4944
4945         for (i = 0;i < r_refdef.scene.numentities;i++)
4946         {
4947                 if (!r_refdef.viewcache.entityvisible[i])
4948                         continue;
4949                 ent = r_refdef.scene.entities[i];
4950                 if (ent->model && ent->model->DrawDebug != NULL)
4951                         ent->model->DrawDebug(ent);
4952         }
4953 }
4954
4955 static void R_DrawModelsAddWaterPlanes(void)
4956 {
4957         int i;
4958         entity_render_t *ent;
4959
4960         for (i = 0;i < r_refdef.scene.numentities;i++)
4961         {
4962                 if (!r_refdef.viewcache.entityvisible[i])
4963                         continue;
4964                 ent = r_refdef.scene.entities[i];
4965                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4966                         ent->model->DrawAddWaterPlanes(ent);
4967         }
4968 }
4969
4970 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4971 {
4972         if (r_hdr_irisadaptation.integer)
4973         {
4974                 vec3_t ambient;
4975                 vec3_t diffuse;
4976                 vec3_t diffusenormal;
4977                 vec_t brightness;
4978                 vec_t goal;
4979                 vec_t adjust;
4980                 vec_t current;
4981                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4982                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4983                 brightness = max(0.0000001f, brightness);
4984                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4985                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4986                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4987                 current = r_hdr_irisadaptation_value.value;
4988                 if (current < goal)
4989                         current = min(current + adjust, goal);
4990                 else if (current > goal)
4991                         current = max(current - adjust, goal);
4992                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4993                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4994         }
4995         else if (r_hdr_irisadaptation_value.value != 1.0f)
4996                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4997 }
4998
4999 static void R_View_SetFrustum(const int *scissor)
5000 {
5001         int i;
5002         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5003         vec3_t forward, left, up, origin, v;
5004
5005         if(scissor)
5006         {
5007                 // flipped x coordinates (because x points left here)
5008                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5009                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5010
5011                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5012                 switch(vid.renderpath)
5013                 {
5014                         case RENDERPATH_D3D9:
5015                         case RENDERPATH_D3D10:
5016                         case RENDERPATH_D3D11:
5017                         case RENDERPATH_SOFT:
5018                                 // non-flipped y coordinates
5019                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5020                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5021                                 break;
5022                         case RENDERPATH_GL11:
5023                         case RENDERPATH_GL13:
5024                         case RENDERPATH_GL20:
5025                         case RENDERPATH_GLES2:
5026                                 // non-flipped y coordinates
5027                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5028                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5029                                 break;
5030                 }
5031         }
5032
5033         // we can't trust r_refdef.view.forward and friends in reflected scenes
5034         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5035
5036 #if 0
5037         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5038         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5039         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5040         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5041         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5042         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5043         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5044         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5045         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5046         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5047         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5048         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5049 #endif
5050
5051 #if 0
5052         zNear = r_refdef.nearclip;
5053         nudge = 1.0 - 1.0 / (1<<23);
5054         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5055         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5056         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5057         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5058         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5059         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5060         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5061         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5062 #endif
5063
5064
5065
5066 #if 0
5067         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5068         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5069         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5070         r_refdef.view.frustum[0].dist = m[15] - m[12];
5071
5072         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5073         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5074         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5075         r_refdef.view.frustum[1].dist = m[15] + m[12];
5076
5077         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5078         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5079         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5080         r_refdef.view.frustum[2].dist = m[15] - m[13];
5081
5082         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5083         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5084         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5085         r_refdef.view.frustum[3].dist = m[15] + m[13];
5086
5087         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5088         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5089         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5090         r_refdef.view.frustum[4].dist = m[15] - m[14];
5091
5092         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5093         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5094         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5095         r_refdef.view.frustum[5].dist = m[15] + m[14];
5096 #endif
5097
5098         if (r_refdef.view.useperspective)
5099         {
5100                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5101                 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]);
5102                 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]);
5103                 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]);
5104                 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]);
5105
5106                 // then the normals from the corners relative to origin
5107                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5108                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5109                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5110                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5111
5112                 // in a NORMAL view, forward cross left == up
5113                 // in a REFLECTED view, forward cross left == down
5114                 // so our cross products above need to be adjusted for a left handed coordinate system
5115                 CrossProduct(forward, left, v);
5116                 if(DotProduct(v, up) < 0)
5117                 {
5118                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5119                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5120                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5121                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5122                 }
5123
5124                 // Leaving those out was a mistake, those were in the old code, and they
5125                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5126                 // I couldn't reproduce it after adding those normalizations. --blub
5127                 VectorNormalize(r_refdef.view.frustum[0].normal);
5128                 VectorNormalize(r_refdef.view.frustum[1].normal);
5129                 VectorNormalize(r_refdef.view.frustum[2].normal);
5130                 VectorNormalize(r_refdef.view.frustum[3].normal);
5131
5132                 // make the corners absolute
5133                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5134                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5135                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5136                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5137
5138                 // one more normal
5139                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5140
5141                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5142                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5143                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5144                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5145                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5146         }
5147         else
5148         {
5149                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5150                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5151                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5152                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5153                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5154                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5155                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5156                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5157                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5158                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5159         }
5160         r_refdef.view.numfrustumplanes = 5;
5161
5162         if (r_refdef.view.useclipplane)
5163         {
5164                 r_refdef.view.numfrustumplanes = 6;
5165                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5166         }
5167
5168         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5169                 PlaneClassify(r_refdef.view.frustum + i);
5170
5171         // LordHavoc: note to all quake engine coders, Quake had a special case
5172         // for 90 degrees which assumed a square view (wrong), so I removed it,
5173         // Quake2 has it disabled as well.
5174
5175         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5176         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5177         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5178         //PlaneClassify(&frustum[0]);
5179
5180         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5181         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5182         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5183         //PlaneClassify(&frustum[1]);
5184
5185         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5186         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5187         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5188         //PlaneClassify(&frustum[2]);
5189
5190         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5191         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5192         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5193         //PlaneClassify(&frustum[3]);
5194
5195         // nearclip plane
5196         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5197         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5198         //PlaneClassify(&frustum[4]);
5199 }
5200
5201 void R_View_UpdateWithScissor(const int *myscissor)
5202 {
5203         R_Main_ResizeViewCache();
5204         R_View_SetFrustum(myscissor);
5205         R_View_WorldVisibility(r_refdef.view.useclipplane);
5206         R_View_UpdateEntityVisible();
5207         R_View_UpdateEntityLighting();
5208 }
5209
5210 void R_View_Update(void)
5211 {
5212         R_Main_ResizeViewCache();
5213         R_View_SetFrustum(NULL);
5214         R_View_WorldVisibility(r_refdef.view.useclipplane);
5215         R_View_UpdateEntityVisible();
5216         R_View_UpdateEntityLighting();
5217 }
5218
5219 void R_SetupView(qboolean allowwaterclippingplane)
5220 {
5221         const float *customclipplane = NULL;
5222         float plane[4];
5223         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5224         {
5225                 // LordHavoc: couldn't figure out how to make this approach the
5226                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5227                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5228                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5229                         dist = r_refdef.view.clipplane.dist;
5230                 plane[0] = r_refdef.view.clipplane.normal[0];
5231                 plane[1] = r_refdef.view.clipplane.normal[1];
5232                 plane[2] = r_refdef.view.clipplane.normal[2];
5233                 plane[3] = dist;
5234                 customclipplane = plane;
5235         }
5236
5237         if (!r_refdef.view.useperspective)
5238                 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);
5239         else if (vid.stencil && r_useinfinitefarclip.integer)
5240                 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);
5241         else
5242                 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);
5243         R_SetViewport(&r_refdef.view.viewport);
5244 }
5245
5246 void R_EntityMatrix(const matrix4x4_t *matrix)
5247 {
5248         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5249         {
5250                 gl_modelmatrixchanged = false;
5251                 gl_modelmatrix = *matrix;
5252                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5253                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5254                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5255                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5256                 CHECKGLERROR
5257                 switch(vid.renderpath)
5258                 {
5259                 case RENDERPATH_D3D9:
5260 #ifdef SUPPORTD3D
5261                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5262                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5263 #endif
5264                         break;
5265                 case RENDERPATH_D3D10:
5266                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5267                         break;
5268                 case RENDERPATH_D3D11:
5269                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5270                         break;
5271                 case RENDERPATH_GL13:
5272                 case RENDERPATH_GL11:
5273                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5274                         break;
5275                 case RENDERPATH_SOFT:
5276                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5277                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5278                         break;
5279                 case RENDERPATH_GL20:
5280                 case RENDERPATH_GLES2:
5281                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5282                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5283                         break;
5284                 }
5285         }
5286 }
5287
5288 void R_ResetViewRendering2D(void)
5289 {
5290         r_viewport_t viewport;
5291         DrawQ_Finish();
5292
5293         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5294         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);
5295         R_SetViewport(&viewport);
5296         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5297         GL_Color(1, 1, 1, 1);
5298         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5299         GL_BlendFunc(GL_ONE, GL_ZERO);
5300         GL_ScissorTest(false);
5301         GL_DepthMask(false);
5302         GL_DepthRange(0, 1);
5303         GL_DepthTest(false);
5304         GL_DepthFunc(GL_LEQUAL);
5305         R_EntityMatrix(&identitymatrix);
5306         R_Mesh_ResetTextureState();
5307         GL_PolygonOffset(0, 0);
5308         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5309         switch(vid.renderpath)
5310         {
5311         case RENDERPATH_GL11:
5312         case RENDERPATH_GL13:
5313         case RENDERPATH_GL20:
5314         case RENDERPATH_GLES2:
5315                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5316                 break;
5317         case RENDERPATH_D3D9:
5318         case RENDERPATH_D3D10:
5319         case RENDERPATH_D3D11:
5320         case RENDERPATH_SOFT:
5321                 break;
5322         }
5323         GL_CullFace(GL_NONE);
5324 }
5325
5326 void R_ResetViewRendering3D(void)
5327 {
5328         DrawQ_Finish();
5329
5330         R_SetupView(true);
5331         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5332         GL_Color(1, 1, 1, 1);
5333         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5334         GL_BlendFunc(GL_ONE, GL_ZERO);
5335         GL_ScissorTest(true);
5336         GL_DepthMask(true);
5337         GL_DepthRange(0, 1);
5338         GL_DepthTest(true);
5339         GL_DepthFunc(GL_LEQUAL);
5340         R_EntityMatrix(&identitymatrix);
5341         R_Mesh_ResetTextureState();
5342         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5343         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5344         switch(vid.renderpath)
5345         {
5346         case RENDERPATH_GL11:
5347         case RENDERPATH_GL13:
5348         case RENDERPATH_GL20:
5349         case RENDERPATH_GLES2:
5350                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5351                 break;
5352         case RENDERPATH_D3D9:
5353         case RENDERPATH_D3D10:
5354         case RENDERPATH_D3D11:
5355         case RENDERPATH_SOFT:
5356                 break;
5357         }
5358         GL_CullFace(r_refdef.view.cullface_back);
5359 }
5360
5361 /*
5362 ================
5363 R_RenderView_UpdateViewVectors
5364 ================
5365 */
5366 static void R_RenderView_UpdateViewVectors(void)
5367 {
5368         // break apart the view matrix into vectors for various purposes
5369         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5370         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5371         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5372         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5373         // make an inverted copy of the view matrix for tracking sprites
5374         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5375 }
5376
5377 void R_RenderScene(void);
5378 void R_RenderWaterPlanes(void);
5379
5380 static void R_Water_StartFrame(void)
5381 {
5382         int i;
5383         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5384         r_waterstate_waterplane_t *p;
5385
5386         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5387                 return;
5388
5389         switch(vid.renderpath)
5390         {
5391         case RENDERPATH_GL20:
5392         case RENDERPATH_D3D9:
5393         case RENDERPATH_D3D10:
5394         case RENDERPATH_D3D11:
5395         case RENDERPATH_SOFT:
5396         case RENDERPATH_GLES2:
5397                 break;
5398         case RENDERPATH_GL13:
5399         case RENDERPATH_GL11:
5400                 return;
5401         }
5402
5403         // set waterwidth and waterheight to the water resolution that will be
5404         // used (often less than the screen resolution for faster rendering)
5405         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5406         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5407
5408         // calculate desired texture sizes
5409         // can't use water if the card does not support the texture size
5410         if (!r_water.integer || r_showsurfaces.integer)
5411                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5412         else if (vid.support.arb_texture_non_power_of_two)
5413         {
5414                 texturewidth = waterwidth;
5415                 textureheight = waterheight;
5416                 camerawidth = waterwidth;
5417                 cameraheight = waterheight;
5418         }
5419         else
5420         {
5421                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5422                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5423                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5424                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5425         }
5426
5427         // allocate textures as needed
5428         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5429         {
5430                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5431                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5432                 {
5433                         if (p->texture_refraction)
5434                                 R_FreeTexture(p->texture_refraction);
5435                         p->texture_refraction = NULL;
5436                         if (p->texture_reflection)
5437                                 R_FreeTexture(p->texture_reflection);
5438                         p->texture_reflection = NULL;
5439                         if (p->texture_camera)
5440                                 R_FreeTexture(p->texture_camera);
5441                         p->texture_camera = NULL;
5442                 }
5443                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5444                 r_waterstate.texturewidth = texturewidth;
5445                 r_waterstate.textureheight = textureheight;
5446                 r_waterstate.camerawidth = camerawidth;
5447                 r_waterstate.cameraheight = cameraheight;
5448         }
5449
5450         if (r_waterstate.texturewidth)
5451         {
5452                 r_waterstate.enabled = true;
5453
5454                 // when doing a reduced render (HDR) we want to use a smaller area
5455                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5456                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5457
5458                 // set up variables that will be used in shader setup
5459                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5460                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5461                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5462                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5463         }
5464
5465         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5466         r_waterstate.numwaterplanes = 0;
5467 }
5468
5469 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5470 {
5471         int triangleindex, planeindex;
5472         const int *e;
5473         vec3_t vert[3];
5474         vec3_t normal;
5475         vec3_t center;
5476         mplane_t plane;
5477         r_waterstate_waterplane_t *p;
5478         texture_t *t = R_GetCurrentTexture(surface->texture);
5479
5480         // just use the first triangle with a valid normal for any decisions
5481         VectorClear(normal);
5482         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5483         {
5484                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5485                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5486                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5487                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5488                 if (VectorLength2(normal) >= 0.001)
5489                         break;
5490         }
5491
5492         VectorCopy(normal, plane.normal);
5493         VectorNormalize(plane.normal);
5494         plane.dist = DotProduct(vert[0], plane.normal);
5495         PlaneClassify(&plane);
5496         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5497         {
5498                 // skip backfaces (except if nocullface is set)
5499                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5500                         return;
5501                 VectorNegate(plane.normal, plane.normal);
5502                 plane.dist *= -1;
5503                 PlaneClassify(&plane);
5504         }
5505
5506
5507         // find a matching plane if there is one
5508         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5509                 if(p->camera_entity == t->camera_entity)
5510                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5511                                 break;
5512         if (planeindex >= r_waterstate.maxwaterplanes)
5513                 return; // nothing we can do, out of planes
5514
5515         // if this triangle does not fit any known plane rendered this frame, add one
5516         if (planeindex >= r_waterstate.numwaterplanes)
5517         {
5518                 // store the new plane
5519                 r_waterstate.numwaterplanes++;
5520                 p->plane = plane;
5521                 // clear materialflags and pvs
5522                 p->materialflags = 0;
5523                 p->pvsvalid = false;
5524                 p->camera_entity = t->camera_entity;
5525                 VectorCopy(surface->mins, p->mins);
5526                 VectorCopy(surface->maxs, p->maxs);
5527         }
5528         else
5529         {
5530                 // merge mins/maxs
5531                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5532                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5533                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5534                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5535                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5536                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5537         }
5538         // merge this surface's materialflags into the waterplane
5539         p->materialflags |= t->currentmaterialflags;
5540         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5541         {
5542                 // merge this surface's PVS into the waterplane
5543                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5544                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5545                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5546                 {
5547                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5548                         p->pvsvalid = true;
5549                 }
5550         }
5551 }
5552
5553 static void R_Water_ProcessPlanes(void)
5554 {
5555         int myscissor[4];
5556         r_refdef_view_t originalview;
5557         r_refdef_view_t myview;
5558         int planeindex;
5559         r_waterstate_waterplane_t *p;
5560         vec3_t visorigin;
5561
5562         originalview = r_refdef.view;
5563
5564         // make sure enough textures are allocated
5565         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5566         {
5567                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5568                 {
5569                         if (!p->texture_refraction)
5570                                 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);
5571                         if (!p->texture_refraction)
5572                                 goto error;
5573                 }
5574                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5575                 {
5576                         if (!p->texture_camera)
5577                                 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);
5578                         if (!p->texture_camera)
5579                                 goto error;
5580                 }
5581
5582                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5583                 {
5584                         if (!p->texture_reflection)
5585                                 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);
5586                         if (!p->texture_reflection)
5587                                 goto error;
5588                 }
5589         }
5590
5591         // render views
5592         r_refdef.view = originalview;
5593         r_refdef.view.showdebug = false;
5594         r_refdef.view.width = r_waterstate.waterwidth;
5595         r_refdef.view.height = r_waterstate.waterheight;
5596         r_refdef.view.useclipplane = true;
5597         myview = r_refdef.view;
5598         r_waterstate.renderingscene = true;
5599         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5600         {
5601                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5602                 {
5603                         r_refdef.view = myview;
5604                         if(r_water_scissormode.integer)
5605                         {
5606                                 R_SetupView(true);
5607                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5608                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5609                         }
5610
5611                         // render reflected scene and copy into texture
5612                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5613                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5614                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5615                         r_refdef.view.clipplane = p->plane;
5616
5617                         // reverse the cullface settings for this render
5618                         r_refdef.view.cullface_front = GL_FRONT;
5619                         r_refdef.view.cullface_back = GL_BACK;
5620                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5621                         {
5622                                 r_refdef.view.usecustompvs = true;
5623                                 if (p->pvsvalid)
5624                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5625                                 else
5626                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5627                         }
5628
5629                         R_ResetViewRendering3D();
5630                         R_ClearScreen(r_refdef.fogenabled);
5631                         if(r_water_scissormode.integer & 2)
5632                                 R_View_UpdateWithScissor(myscissor);
5633                         else
5634                                 R_View_Update();
5635                         if(r_water_scissormode.integer & 1)
5636                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5637                         R_RenderScene();
5638
5639                         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);
5640                 }
5641
5642                 // render the normal view scene and copy into texture
5643                 // (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)
5644                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5645                 {
5646                         r_refdef.view = myview;
5647                         if(r_water_scissormode.integer)
5648                         {
5649                                 R_SetupView(true);
5650                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5651                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5652                         }
5653
5654                         r_waterstate.renderingrefraction = true;
5655
5656                         r_refdef.view.clipplane = p->plane;
5657                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5658                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5659
5660                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5661                         {
5662                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5663                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5664                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5665                                 R_RenderView_UpdateViewVectors();
5666                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5667                                 {
5668                                         r_refdef.view.usecustompvs = true;
5669                                         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);
5670                                 }
5671                         }
5672
5673                         PlaneClassify(&r_refdef.view.clipplane);
5674
5675                         R_ResetViewRendering3D();
5676                         R_ClearScreen(r_refdef.fogenabled);
5677                         if(r_water_scissormode.integer & 2)
5678                                 R_View_UpdateWithScissor(myscissor);
5679                         else
5680                                 R_View_Update();
5681                         if(r_water_scissormode.integer & 1)
5682                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5683                         R_RenderScene();
5684
5685                         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);
5686                         r_waterstate.renderingrefraction = false;
5687                 }
5688                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5689                 {
5690                         r_refdef.view = myview;
5691
5692                         r_refdef.view.clipplane = p->plane;
5693                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5694                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5695
5696                         r_refdef.view.width = r_waterstate.camerawidth;
5697                         r_refdef.view.height = r_waterstate.cameraheight;
5698                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5699                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5700
5701                         if(p->camera_entity)
5702                         {
5703                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5704                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5705                         }
5706
5707                         // note: all of the view is used for displaying... so
5708                         // there is no use in scissoring
5709
5710                         // reverse the cullface settings for this render
5711                         r_refdef.view.cullface_front = GL_FRONT;
5712                         r_refdef.view.cullface_back = GL_BACK;
5713                         // also reverse the view matrix
5714                         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
5715                         R_RenderView_UpdateViewVectors();
5716                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5717                         {
5718                                 r_refdef.view.usecustompvs = true;
5719                                 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);
5720                         }
5721                         
5722                         // camera needs no clipplane
5723                         r_refdef.view.useclipplane = false;
5724
5725                         PlaneClassify(&r_refdef.view.clipplane);
5726
5727                         R_ResetViewRendering3D();
5728                         R_ClearScreen(r_refdef.fogenabled);
5729                         R_View_Update();
5730                         R_RenderScene();
5731
5732                         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);
5733                         r_waterstate.renderingrefraction = false;
5734                 }
5735
5736         }
5737         r_waterstate.renderingscene = false;
5738         r_refdef.view = originalview;
5739         R_ResetViewRendering3D();
5740         R_ClearScreen(r_refdef.fogenabled);
5741         R_View_Update();
5742         return;
5743 error:
5744         r_refdef.view = originalview;
5745         r_waterstate.renderingscene = false;
5746         Cvar_SetValueQuick(&r_water, 0);
5747         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5748         return;
5749 }
5750
5751 void R_Bloom_StartFrame(void)
5752 {
5753         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5754
5755         switch(vid.renderpath)
5756         {
5757         case RENDERPATH_GL20:
5758         case RENDERPATH_D3D9:
5759         case RENDERPATH_D3D10:
5760         case RENDERPATH_D3D11:
5761         case RENDERPATH_SOFT:
5762         case RENDERPATH_GLES2:
5763                 break;
5764         case RENDERPATH_GL13:
5765         case RENDERPATH_GL11:
5766                 return;
5767         }
5768
5769         // set bloomwidth and bloomheight to the bloom resolution that will be
5770         // used (often less than the screen resolution for faster rendering)
5771         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5772         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5773         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5774         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5775         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5776
5777         // calculate desired texture sizes
5778         if (vid.support.arb_texture_non_power_of_two)
5779         {
5780                 screentexturewidth = r_refdef.view.width;
5781                 screentextureheight = r_refdef.view.height;
5782                 bloomtexturewidth = r_bloomstate.bloomwidth;
5783                 bloomtextureheight = r_bloomstate.bloomheight;
5784         }
5785         else
5786         {
5787                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5788                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5789                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5790                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5791         }
5792
5793         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))
5794         {
5795                 Cvar_SetValueQuick(&r_hdr, 0);
5796                 Cvar_SetValueQuick(&r_bloom, 0);
5797                 Cvar_SetValueQuick(&r_motionblur, 0);
5798                 Cvar_SetValueQuick(&r_damageblur, 0);
5799         }
5800
5801         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)))
5802                 screentexturewidth = screentextureheight = 0;
5803         if (!r_hdr.integer && !r_bloom.integer)
5804                 bloomtexturewidth = bloomtextureheight = 0;
5805
5806         // allocate textures as needed
5807         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5808         {
5809                 if (r_bloomstate.texture_screen)
5810                         R_FreeTexture(r_bloomstate.texture_screen);
5811                 r_bloomstate.texture_screen = NULL;
5812                 r_bloomstate.screentexturewidth = screentexturewidth;
5813                 r_bloomstate.screentextureheight = screentextureheight;
5814                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5815                         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);
5816         }
5817         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5818         {
5819                 if (r_bloomstate.texture_bloom)
5820                         R_FreeTexture(r_bloomstate.texture_bloom);
5821                 r_bloomstate.texture_bloom = NULL;
5822                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5823                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5824                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5825                         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);
5826         }
5827
5828         // when doing a reduced render (HDR) we want to use a smaller area
5829         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5830         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5831         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5832         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5833         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5834
5835         // set up a texcoord array for the full resolution screen image
5836         // (we have to keep this around to copy back during final render)
5837         r_bloomstate.screentexcoord2f[0] = 0;
5838         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5839         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5840         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5841         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5842         r_bloomstate.screentexcoord2f[5] = 0;
5843         r_bloomstate.screentexcoord2f[6] = 0;
5844         r_bloomstate.screentexcoord2f[7] = 0;
5845
5846         // set up a texcoord array for the reduced resolution bloom image
5847         // (which will be additive blended over the screen image)
5848         r_bloomstate.bloomtexcoord2f[0] = 0;
5849         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5850         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5851         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5852         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5853         r_bloomstate.bloomtexcoord2f[5] = 0;
5854         r_bloomstate.bloomtexcoord2f[6] = 0;
5855         r_bloomstate.bloomtexcoord2f[7] = 0;
5856
5857         switch(vid.renderpath)
5858         {
5859         case RENDERPATH_GL11:
5860         case RENDERPATH_GL13:
5861         case RENDERPATH_GL20:
5862         case RENDERPATH_SOFT:
5863         case RENDERPATH_GLES2:
5864                 break;
5865         case RENDERPATH_D3D9:
5866         case RENDERPATH_D3D10:
5867         case RENDERPATH_D3D11:
5868                 {
5869                         int i;
5870                         for (i = 0;i < 4;i++)
5871                         {
5872                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5873                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5874                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5875                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5876                         }
5877                 }
5878                 break;
5879         }
5880
5881         if (r_hdr.integer || r_bloom.integer)
5882         {
5883                 r_bloomstate.enabled = true;
5884                 r_bloomstate.hdr = r_hdr.integer != 0;
5885         }
5886
5887         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);
5888 }
5889
5890 void R_Bloom_CopyBloomTexture(float colorscale)
5891 {
5892         r_refdef.stats.bloom++;
5893
5894         // scale down screen texture to the bloom texture size
5895         CHECKGLERROR
5896         R_SetViewport(&r_bloomstate.viewport);
5897         GL_BlendFunc(GL_ONE, GL_ZERO);
5898         GL_Color(colorscale, colorscale, colorscale, 1);
5899         // 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...
5900         switch(vid.renderpath)
5901         {
5902         case RENDERPATH_GL11:
5903         case RENDERPATH_GL13:
5904         case RENDERPATH_GL20:
5905         case RENDERPATH_SOFT:
5906         case RENDERPATH_GLES2:
5907                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5908                 break;
5909         case RENDERPATH_D3D9:
5910         case RENDERPATH_D3D10:
5911         case RENDERPATH_D3D11:
5912                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5913                 break;
5914         }
5915         // TODO: do boxfilter scale-down in shader?
5916         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5917         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5918         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5919
5920         // we now have a bloom image in the framebuffer
5921         // copy it into the bloom image texture for later processing
5922         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);
5923         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5924 }
5925
5926 void R_Bloom_CopyHDRTexture(void)
5927 {
5928         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);
5929         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5930 }
5931
5932 void R_Bloom_MakeTexture(void)
5933 {
5934         int x, range, dir;
5935         float xoffset, yoffset, r, brighten;
5936
5937         r_refdef.stats.bloom++;
5938
5939         R_ResetViewRendering2D();
5940
5941         // we have a bloom image in the framebuffer
5942         CHECKGLERROR
5943         R_SetViewport(&r_bloomstate.viewport);
5944
5945         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5946         {
5947                 x *= 2;
5948                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5949                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5950                 GL_Color(r,r,r,1);
5951                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5952                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5953                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5954                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5955
5956                 // copy the vertically blurred bloom view to a texture
5957                 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);
5958                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5959         }
5960
5961         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5962         brighten = r_bloom_brighten.value;
5963         if (r_hdr.integer)
5964                 brighten *= r_hdr_range.value;
5965         brighten = sqrt(brighten);
5966         if(range >= 1)
5967                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5968         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5969
5970         for (dir = 0;dir < 2;dir++)
5971         {
5972                 // blend on at multiple vertical offsets to achieve a vertical blur
5973                 // TODO: do offset blends using GLSL
5974                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5975                 GL_BlendFunc(GL_ONE, GL_ZERO);
5976                 for (x = -range;x <= range;x++)
5977                 {
5978                         if (!dir){xoffset = 0;yoffset = x;}
5979                         else {xoffset = x;yoffset = 0;}
5980                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5981                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5982                         // compute a texcoord array with the specified x and y offset
5983                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5984                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5985                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5986                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5987                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5988                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5989                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5990                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5991                         // this r value looks like a 'dot' particle, fading sharply to
5992                         // black at the edges
5993                         // (probably not realistic but looks good enough)
5994                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5995                         //r = brighten/(range*2+1);
5996                         r = brighten / (range * 2 + 1);
5997                         if(range >= 1)
5998                                 r *= (1 - x*x/(float)(range*range));
5999                         GL_Color(r, r, r, 1);
6000                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6001                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6002                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6003                         GL_BlendFunc(GL_ONE, GL_ONE);
6004                 }
6005
6006                 // copy the vertically blurred bloom view to a texture
6007                 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);
6008                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6009         }
6010 }
6011
6012 void R_HDR_RenderBloomTexture(void)
6013 {
6014         int oldwidth, oldheight;
6015         float oldcolorscale;
6016         qboolean oldwaterstate;
6017
6018         oldwaterstate = r_waterstate.enabled;
6019         oldcolorscale = r_refdef.view.colorscale;
6020         oldwidth = r_refdef.view.width;
6021         oldheight = r_refdef.view.height;
6022         r_refdef.view.width = r_bloomstate.bloomwidth;
6023         r_refdef.view.height = r_bloomstate.bloomheight;
6024
6025         if(r_hdr.integer < 2)
6026                 r_waterstate.enabled = false;
6027
6028         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6029         // TODO: add exposure compensation features
6030         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6031
6032         r_refdef.view.showdebug = false;
6033         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6034
6035         R_ResetViewRendering3D();
6036
6037         R_ClearScreen(r_refdef.fogenabled);
6038         if (r_timereport_active)
6039                 R_TimeReport("HDRclear");
6040
6041         R_View_Update();
6042         if (r_timereport_active)
6043                 R_TimeReport("visibility");
6044
6045         // only do secondary renders with HDR if r_hdr is 2 or higher
6046         r_waterstate.numwaterplanes = 0;
6047         if (r_waterstate.enabled)
6048                 R_RenderWaterPlanes();
6049
6050         r_refdef.view.showdebug = true;
6051         R_RenderScene();
6052         r_waterstate.numwaterplanes = 0;
6053
6054         R_ResetViewRendering2D();
6055
6056         R_Bloom_CopyHDRTexture();
6057         R_Bloom_MakeTexture();
6058
6059         // restore the view settings
6060         r_waterstate.enabled = oldwaterstate;
6061         r_refdef.view.width = oldwidth;
6062         r_refdef.view.height = oldheight;
6063         r_refdef.view.colorscale = oldcolorscale;
6064
6065         R_ResetViewRendering3D();
6066
6067         R_ClearScreen(r_refdef.fogenabled);
6068         if (r_timereport_active)
6069                 R_TimeReport("viewclear");
6070 }
6071
6072 static void R_BlendView(void)
6073 {
6074         unsigned int permutation;
6075         float uservecs[4][4];
6076
6077         switch (vid.renderpath)
6078         {
6079         case RENDERPATH_GL20:
6080         case RENDERPATH_D3D9:
6081         case RENDERPATH_D3D10:
6082         case RENDERPATH_D3D11:
6083         case RENDERPATH_SOFT:
6084         case RENDERPATH_GLES2:
6085                 permutation =
6086                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6087                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6088                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6089                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6090                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6091
6092                 if (r_bloomstate.texture_screen)
6093                 {
6094                         // make sure the buffer is available
6095                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6096
6097                         R_ResetViewRendering2D();
6098
6099                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6100                         {
6101                                 // declare variables
6102                                 float speed;
6103                                 static float avgspeed;
6104
6105                                 speed = VectorLength(cl.movement_velocity);
6106
6107                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6108                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6109
6110                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6111                                 speed = bound(0, speed, 1);
6112                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6113
6114                                 // calculate values into a standard alpha
6115                                 cl.motionbluralpha = 1 - exp(-
6116                                                 (
6117                                                  (r_motionblur.value * speed / 80)
6118                                                  +
6119                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6120                                                 )
6121                                                 /
6122                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6123                                            );
6124
6125                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6126                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6127                                 // apply the blur
6128                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6129                                 {
6130                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6131                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6132                                         switch(vid.renderpath)
6133                                         {
6134                                         case RENDERPATH_GL11:
6135                                         case RENDERPATH_GL13:
6136                                         case RENDERPATH_GL20:
6137                                         case RENDERPATH_SOFT:
6138                                         case RENDERPATH_GLES2:
6139                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6140                                                 break;
6141                                         case RENDERPATH_D3D9:
6142                                         case RENDERPATH_D3D10:
6143                                         case RENDERPATH_D3D11:
6144                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6145                                                 break;
6146                                         }
6147                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6148                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6149                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6150                                 }
6151                         }
6152
6153                         // copy view into the screen texture
6154                         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);
6155                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6156                 }
6157                 else if (!r_bloomstate.texture_bloom)
6158                 {
6159                         // we may still have to do view tint...
6160                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6161                         {
6162                                 // apply a color tint to the whole view
6163                                 R_ResetViewRendering2D();
6164                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6165                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6166                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6167                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6168                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6169                         }
6170                         break; // no screen processing, no bloom, skip it
6171                 }
6172
6173                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6174                 {
6175                         // render simple bloom effect
6176                         // copy the screen and shrink it and darken it for the bloom process
6177                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6178                         // make the bloom texture
6179                         R_Bloom_MakeTexture();
6180                 }
6181
6182 #if _MSC_VER >= 1400
6183 #define sscanf sscanf_s
6184 #endif
6185                 memset(uservecs, 0, sizeof(uservecs));
6186                 if (r_glsl_postprocess_uservec1_enable.integer)
6187                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6188                 if (r_glsl_postprocess_uservec2_enable.integer)
6189                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6190                 if (r_glsl_postprocess_uservec3_enable.integer)
6191                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6192                 if (r_glsl_postprocess_uservec4_enable.integer)
6193                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6194
6195                 R_ResetViewRendering2D();
6196                 GL_Color(1, 1, 1, 1);
6197                 GL_BlendFunc(GL_ONE, GL_ZERO);
6198
6199                 switch(vid.renderpath)
6200                 {
6201                 case RENDERPATH_GL20:
6202                 case RENDERPATH_GLES2:
6203                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6204                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6205                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6206                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6207                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6208                         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]);
6209                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6210                         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]);
6211                         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]);
6212                         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]);
6213                         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]);
6214                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6215                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6216                         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);
6217                         break;
6218                 case RENDERPATH_D3D9:
6219 #ifdef SUPPORTD3D
6220                         // 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...
6221                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6222                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6223                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6224                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6225                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6226                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6227                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6228                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6229                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6230                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6231                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6232                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6233                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6234                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6235 #endif
6236                         break;
6237                 case RENDERPATH_D3D10:
6238                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6239                         break;
6240                 case RENDERPATH_D3D11:
6241                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6242                         break;
6243                 case RENDERPATH_SOFT:
6244                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6245                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6246                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6247                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6248                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6249                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6250                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6251                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6252                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6253                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6254                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6255                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6256                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6257                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6258                         break;
6259                 default:
6260                         break;
6261                 }
6262                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6263                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6264                 break;
6265         case RENDERPATH_GL13:
6266         case RENDERPATH_GL11:
6267                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6268                 {
6269                         // apply a color tint to the whole view
6270                         R_ResetViewRendering2D();
6271                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6273                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6274                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6275                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6276                 }
6277                 break;
6278         }
6279 }
6280
6281 matrix4x4_t r_waterscrollmatrix;
6282
6283 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6284 {
6285         if (r_refdef.fog_density)
6286         {
6287                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6288                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6289                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6290
6291                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6292                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6293                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6294                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6295
6296                 {
6297                         vec3_t fogvec;
6298                         VectorCopy(r_refdef.fogcolor, fogvec);
6299                         //   color.rgb *= ContrastBoost * SceneBrightness;
6300                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6301                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6302                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6303                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6304                 }
6305         }
6306 }
6307
6308 void R_UpdateVariables(void)
6309 {
6310         R_Textures_Frame();
6311
6312         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6313
6314         r_refdef.farclip = r_farclip_base.value;
6315         if (r_refdef.scene.worldmodel)
6316                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6317         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6318
6319         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6320                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6321         r_refdef.polygonfactor = 0;
6322         r_refdef.polygonoffset = 0;
6323         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6324         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6325
6326         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6327         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6328         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6329         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6330         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6331         if (FAKELIGHT_ENABLED)
6332         {
6333                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6334         }
6335         if (r_showsurfaces.integer)
6336         {
6337                 r_refdef.scene.rtworld = false;
6338                 r_refdef.scene.rtworldshadows = false;
6339                 r_refdef.scene.rtdlight = false;
6340                 r_refdef.scene.rtdlightshadows = false;
6341                 r_refdef.lightmapintensity = 0;
6342         }
6343
6344         if (gamemode == GAME_NEHAHRA)
6345         {
6346                 if (gl_fogenable.integer)
6347                 {
6348                         r_refdef.oldgl_fogenable = true;
6349                         r_refdef.fog_density = gl_fogdensity.value;
6350                         r_refdef.fog_red = gl_fogred.value;
6351                         r_refdef.fog_green = gl_foggreen.value;
6352                         r_refdef.fog_blue = gl_fogblue.value;
6353                         r_refdef.fog_alpha = 1;
6354                         r_refdef.fog_start = 0;
6355                         r_refdef.fog_end = gl_skyclip.value;
6356                         r_refdef.fog_height = 1<<30;
6357                         r_refdef.fog_fadedepth = 128;
6358                 }
6359                 else if (r_refdef.oldgl_fogenable)
6360                 {
6361                         r_refdef.oldgl_fogenable = false;
6362                         r_refdef.fog_density = 0;
6363                         r_refdef.fog_red = 0;
6364                         r_refdef.fog_green = 0;
6365                         r_refdef.fog_blue = 0;
6366                         r_refdef.fog_alpha = 0;
6367                         r_refdef.fog_start = 0;
6368                         r_refdef.fog_end = 0;
6369                         r_refdef.fog_height = 1<<30;
6370                         r_refdef.fog_fadedepth = 128;
6371                 }
6372         }
6373
6374         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6375         r_refdef.fog_start = max(0, r_refdef.fog_start);
6376         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6377
6378         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6379
6380         if (r_refdef.fog_density && r_drawfog.integer)
6381         {
6382                 r_refdef.fogenabled = true;
6383                 // this is the point where the fog reaches 0.9986 alpha, which we
6384                 // consider a good enough cutoff point for the texture
6385                 // (0.9986 * 256 == 255.6)
6386                 if (r_fog_exp2.integer)
6387                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6388                 else
6389                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6390                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6391                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6392                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6393                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6394                         R_BuildFogHeightTexture();
6395                 // fog color was already set
6396                 // update the fog texture
6397                 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)
6398                         R_BuildFogTexture();
6399                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6400                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6401         }
6402         else
6403                 r_refdef.fogenabled = false;
6404
6405         switch(vid.renderpath)
6406         {
6407         case RENDERPATH_GL20:
6408         case RENDERPATH_D3D9:
6409         case RENDERPATH_D3D10:
6410         case RENDERPATH_D3D11:
6411         case RENDERPATH_SOFT:
6412         case RENDERPATH_GLES2:
6413                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6414                 {
6415                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6416                         {
6417                                 // build GLSL gamma texture
6418 #define RAMPWIDTH 256
6419                                 unsigned short ramp[RAMPWIDTH * 3];
6420                                 unsigned char rampbgr[RAMPWIDTH][4];
6421                                 int i;
6422
6423                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6424
6425                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6426                                 for(i = 0; i < RAMPWIDTH; ++i)
6427                                 {
6428                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6429                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6430                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6431                                         rampbgr[i][3] = 0;
6432                                 }
6433                                 if (r_texture_gammaramps)
6434                                 {
6435                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6436                                 }
6437                                 else
6438                                 {
6439                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6440                                 }
6441                         }
6442                 }
6443                 else
6444                 {
6445                         // remove GLSL gamma texture
6446                 }
6447                 break;
6448         case RENDERPATH_GL13:
6449         case RENDERPATH_GL11:
6450                 break;
6451         }
6452 }
6453
6454 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6455 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6456 /*
6457 ================
6458 R_SelectScene
6459 ================
6460 */
6461 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6462         if( scenetype != r_currentscenetype ) {
6463                 // store the old scenetype
6464                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6465                 r_currentscenetype = scenetype;
6466                 // move in the new scene
6467                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6468         }
6469 }
6470
6471 /*
6472 ================
6473 R_GetScenePointer
6474 ================
6475 */
6476 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6477 {
6478         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6479         if( scenetype == r_currentscenetype ) {
6480                 return &r_refdef.scene;
6481         } else {
6482                 return &r_scenes_store[ scenetype ];
6483         }
6484 }
6485
6486 /*
6487 ================
6488 R_RenderView
6489 ================
6490 */
6491 int dpsoftrast_test;
6492 void R_RenderView(void)
6493 {
6494         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6495
6496         dpsoftrast_test = r_test.integer;
6497
6498         if (r_timereport_active)
6499                 R_TimeReport("start");
6500         r_textureframe++; // used only by R_GetCurrentTexture
6501         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6502
6503         if(R_CompileShader_CheckStaticParms())
6504                 R_GLSL_Restart_f();
6505
6506         if (!r_drawentities.integer)
6507                 r_refdef.scene.numentities = 0;
6508
6509         R_AnimCache_ClearCache();
6510         R_FrameData_NewFrame();
6511
6512         /* adjust for stereo display */
6513         if(R_Stereo_Active())
6514         {
6515                 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);
6516                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6517         }
6518
6519         if (r_refdef.view.isoverlay)
6520         {
6521                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6522                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6523                 R_TimeReport("depthclear");
6524
6525                 r_refdef.view.showdebug = false;
6526
6527                 r_waterstate.enabled = false;
6528                 r_waterstate.numwaterplanes = 0;
6529
6530                 R_RenderScene();
6531
6532                 r_refdef.view.matrix = originalmatrix;
6533
6534                 CHECKGLERROR
6535                 return;
6536         }
6537
6538         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6539         {
6540                 r_refdef.view.matrix = originalmatrix;
6541                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6542         }
6543
6544         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6545
6546         R_RenderView_UpdateViewVectors();
6547
6548         R_Shadow_UpdateWorldLightSelection();
6549
6550         R_Bloom_StartFrame();
6551         R_Water_StartFrame();
6552
6553         CHECKGLERROR
6554         if (r_timereport_active)
6555                 R_TimeReport("viewsetup");
6556
6557         R_ResetViewRendering3D();
6558
6559         if (r_refdef.view.clear || r_refdef.fogenabled)
6560         {
6561                 R_ClearScreen(r_refdef.fogenabled);
6562                 if (r_timereport_active)
6563                         R_TimeReport("viewclear");
6564         }
6565         r_refdef.view.clear = true;
6566
6567         // this produces a bloom texture to be used in R_BlendView() later
6568         if (r_hdr.integer && r_bloomstate.bloomwidth)
6569         {
6570                 R_HDR_RenderBloomTexture();
6571                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6572                 r_textureframe++; // used only by R_GetCurrentTexture
6573         }
6574
6575         r_refdef.view.showdebug = true;
6576
6577         R_View_Update();
6578         if (r_timereport_active)
6579                 R_TimeReport("visibility");
6580
6581         r_waterstate.numwaterplanes = 0;
6582         if (r_waterstate.enabled)
6583                 R_RenderWaterPlanes();
6584
6585         R_RenderScene();
6586         r_waterstate.numwaterplanes = 0;
6587
6588         R_BlendView();
6589         if (r_timereport_active)
6590                 R_TimeReport("blendview");
6591
6592         GL_Scissor(0, 0, vid.width, vid.height);
6593         GL_ScissorTest(false);
6594
6595         r_refdef.view.matrix = originalmatrix;
6596
6597         CHECKGLERROR
6598 }
6599
6600 void R_RenderWaterPlanes(void)
6601 {
6602         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6603         {
6604                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6605                 if (r_timereport_active)
6606                         R_TimeReport("waterworld");
6607         }
6608
6609         // don't let sound skip if going slow
6610         if (r_refdef.scene.extraupdate)
6611                 S_ExtraUpdate ();
6612
6613         R_DrawModelsAddWaterPlanes();
6614         if (r_timereport_active)
6615                 R_TimeReport("watermodels");
6616
6617         if (r_waterstate.numwaterplanes)
6618         {
6619                 R_Water_ProcessPlanes();
6620                 if (r_timereport_active)
6621                         R_TimeReport("waterscenes");
6622         }
6623 }
6624
6625 extern void R_DrawLightningBeams (void);
6626 extern void VM_CL_AddPolygonsToMeshQueue (void);
6627 extern void R_DrawPortals (void);
6628 extern cvar_t cl_locs_show;
6629 static void R_DrawLocs(void);
6630 static void R_DrawEntityBBoxes(void);
6631 static void R_DrawModelDecals(void);
6632 extern void R_DrawModelShadows(void);
6633 extern void R_DrawModelShadowMaps(void);
6634 extern cvar_t cl_decals_newsystem;
6635 extern qboolean r_shadow_usingdeferredprepass;
6636 void R_RenderScene(void)
6637 {
6638         qboolean shadowmapping = false;
6639
6640         if (r_timereport_active)
6641                 R_TimeReport("beginscene");
6642
6643         r_refdef.stats.renders++;
6644
6645         R_UpdateFogColor();
6646
6647         // don't let sound skip if going slow
6648         if (r_refdef.scene.extraupdate)
6649                 S_ExtraUpdate ();
6650
6651         R_MeshQueue_BeginScene();
6652
6653         R_SkyStartFrame();
6654
6655         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);
6656
6657         if (r_timereport_active)
6658                 R_TimeReport("skystartframe");
6659
6660         if (cl.csqc_vidvars.drawworld)
6661         {
6662                 // don't let sound skip if going slow
6663                 if (r_refdef.scene.extraupdate)
6664                         S_ExtraUpdate ();
6665
6666                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6667                 {
6668                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6669                         if (r_timereport_active)
6670                                 R_TimeReport("worldsky");
6671                 }
6672
6673                 if (R_DrawBrushModelsSky() && r_timereport_active)
6674                         R_TimeReport("bmodelsky");
6675
6676                 if (skyrendermasked && skyrenderlater)
6677                 {
6678                         // we have to force off the water clipping plane while rendering sky
6679                         R_SetupView(false);
6680                         R_Sky();
6681                         R_SetupView(true);
6682                         if (r_timereport_active)
6683                                 R_TimeReport("sky");
6684                 }
6685         }
6686
6687         R_AnimCache_CacheVisibleEntities();
6688         if (r_timereport_active)
6689                 R_TimeReport("animation");
6690
6691         R_Shadow_PrepareLights();
6692         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6693                 R_Shadow_PrepareModelShadows();
6694         if (r_timereport_active)
6695                 R_TimeReport("preparelights");
6696
6697         if (R_Shadow_ShadowMappingEnabled())
6698                 shadowmapping = true;
6699
6700         if (r_shadow_usingdeferredprepass)
6701                 R_Shadow_DrawPrepass();
6702
6703         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6704         {
6705                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6706                 if (r_timereport_active)
6707                         R_TimeReport("worlddepth");
6708         }
6709         if (r_depthfirst.integer >= 2)
6710         {
6711                 R_DrawModelsDepth();
6712                 if (r_timereport_active)
6713                         R_TimeReport("modeldepth");
6714         }
6715
6716         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6717         {
6718                 R_DrawModelShadowMaps();
6719                 R_ResetViewRendering3D();
6720                 // don't let sound skip if going slow
6721                 if (r_refdef.scene.extraupdate)
6722                         S_ExtraUpdate ();
6723         }
6724
6725         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6726         {
6727                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6728                 if (r_timereport_active)
6729                         R_TimeReport("world");
6730         }
6731
6732         // don't let sound skip if going slow
6733         if (r_refdef.scene.extraupdate)
6734                 S_ExtraUpdate ();
6735
6736         R_DrawModels();
6737         if (r_timereport_active)
6738                 R_TimeReport("models");
6739
6740         // don't let sound skip if going slow
6741         if (r_refdef.scene.extraupdate)
6742                 S_ExtraUpdate ();
6743
6744         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6745         {
6746                 R_DrawModelShadows();
6747                 R_ResetViewRendering3D();
6748                 // don't let sound skip if going slow
6749                 if (r_refdef.scene.extraupdate)
6750                         S_ExtraUpdate ();
6751         }
6752
6753         if (!r_shadow_usingdeferredprepass)
6754         {
6755                 R_Shadow_DrawLights();
6756                 if (r_timereport_active)
6757                         R_TimeReport("rtlights");
6758         }
6759
6760         // don't let sound skip if going slow
6761         if (r_refdef.scene.extraupdate)
6762                 S_ExtraUpdate ();
6763
6764         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6765         {
6766                 R_DrawModelShadows();
6767                 R_ResetViewRendering3D();
6768                 // don't let sound skip if going slow
6769                 if (r_refdef.scene.extraupdate)
6770                         S_ExtraUpdate ();
6771         }
6772
6773         if (cl.csqc_vidvars.drawworld)
6774         {
6775                 if (cl_decals_newsystem.integer)
6776                 {
6777                         R_DrawModelDecals();
6778                         if (r_timereport_active)
6779                                 R_TimeReport("modeldecals");
6780                 }
6781                 else
6782                 {
6783                         R_DrawDecals();
6784                         if (r_timereport_active)
6785                                 R_TimeReport("decals");
6786                 }
6787
6788                 R_DrawParticles();
6789                 if (r_timereport_active)
6790                         R_TimeReport("particles");
6791
6792                 R_DrawExplosions();
6793                 if (r_timereport_active)
6794                         R_TimeReport("explosions");
6795
6796                 R_DrawLightningBeams();
6797                 if (r_timereport_active)
6798                         R_TimeReport("lightning");
6799         }
6800
6801         VM_CL_AddPolygonsToMeshQueue();
6802
6803         if (r_refdef.view.showdebug)
6804         {
6805                 if (cl_locs_show.integer)
6806                 {
6807                         R_DrawLocs();
6808                         if (r_timereport_active)
6809                                 R_TimeReport("showlocs");
6810                 }
6811
6812                 if (r_drawportals.integer)
6813                 {
6814                         R_DrawPortals();
6815                         if (r_timereport_active)
6816                                 R_TimeReport("portals");
6817                 }
6818
6819                 if (r_showbboxes.value > 0)
6820                 {
6821                         R_DrawEntityBBoxes();
6822                         if (r_timereport_active)
6823                                 R_TimeReport("bboxes");
6824                 }
6825         }
6826
6827         R_MeshQueue_RenderTransparent();
6828         if (r_timereport_active)
6829                 R_TimeReport("drawtrans");
6830
6831         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))
6832         {
6833                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6834                 if (r_timereport_active)
6835                         R_TimeReport("worlddebug");
6836                 R_DrawModelsDebug();
6837                 if (r_timereport_active)
6838                         R_TimeReport("modeldebug");
6839         }
6840
6841         if (cl.csqc_vidvars.drawworld)
6842         {
6843                 R_Shadow_DrawCoronas();
6844                 if (r_timereport_active)
6845                         R_TimeReport("coronas");
6846         }
6847
6848 #if 0
6849         {
6850                 GL_DepthTest(false);
6851                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6852                 GL_Color(1, 1, 1, 1);
6853                 qglBegin(GL_POLYGON);
6854                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6855                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6856                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6857                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6858                 qglEnd();
6859                 qglBegin(GL_POLYGON);
6860                 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]);
6861                 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]);
6862                 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]);
6863                 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]);
6864                 qglEnd();
6865                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6866         }
6867 #endif
6868
6869         // don't let sound skip if going slow
6870         if (r_refdef.scene.extraupdate)
6871                 S_ExtraUpdate ();
6872
6873         R_ResetViewRendering2D();
6874 }
6875
6876 static const unsigned short bboxelements[36] =
6877 {
6878         5, 1, 3, 5, 3, 7,
6879         6, 2, 0, 6, 0, 4,
6880         7, 3, 2, 7, 2, 6,
6881         4, 0, 1, 4, 1, 5,
6882         4, 5, 7, 4, 7, 6,
6883         1, 0, 2, 1, 2, 3,
6884 };
6885
6886 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6887 {
6888         int i;
6889         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6890
6891         RSurf_ActiveWorldEntity();
6892
6893         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6894         GL_DepthMask(false);
6895         GL_DepthRange(0, 1);
6896         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6897 //      R_Mesh_ResetTextureState();
6898
6899         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6900         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6901         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6902         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6903         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6904         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6905         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6906         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6907         R_FillColors(color4f, 8, cr, cg, cb, ca);
6908         if (r_refdef.fogenabled)
6909         {
6910                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6911                 {
6912                         f1 = RSurf_FogVertex(v);
6913                         f2 = 1 - f1;
6914                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6915                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6916                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6917                 }
6918         }
6919         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6920         R_Mesh_ResetTextureState();
6921         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6922         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6923 }
6924
6925 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6926 {
6927         int i;
6928         float color[4];
6929         prvm_edict_t *edict;
6930         prvm_prog_t *prog_save = prog;
6931
6932         // this function draws bounding boxes of server entities
6933         if (!sv.active)
6934                 return;
6935
6936         GL_CullFace(GL_NONE);
6937         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6938
6939         prog = 0;
6940         SV_VM_Begin();
6941         for (i = 0;i < numsurfaces;i++)
6942         {
6943                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6944                 switch ((int)edict->fields.server->solid)
6945                 {
6946                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6947                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6948                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6949                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6950                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6951                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6952                 }
6953                 color[3] *= r_showbboxes.value;
6954                 color[3] = bound(0, color[3], 1);
6955                 GL_DepthTest(!r_showdisabledepthtest.integer);
6956                 GL_CullFace(r_refdef.view.cullface_front);
6957                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6958         }
6959         SV_VM_End();
6960         prog = prog_save;
6961 }
6962
6963 static void R_DrawEntityBBoxes(void)
6964 {
6965         int i;
6966         prvm_edict_t *edict;
6967         vec3_t center;
6968         prvm_prog_t *prog_save = prog;
6969
6970         // this function draws bounding boxes of server entities
6971         if (!sv.active)
6972                 return;
6973
6974         prog = 0;
6975         SV_VM_Begin();
6976         for (i = 0;i < prog->num_edicts;i++)
6977         {
6978                 edict = PRVM_EDICT_NUM(i);
6979                 if (edict->priv.server->free)
6980                         continue;
6981                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6982                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6983                         continue;
6984                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6985                         continue;
6986                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6987                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6988         }
6989         SV_VM_End();
6990         prog = prog_save;
6991 }
6992
6993 static const int nomodelelement3i[24] =
6994 {
6995         5, 2, 0,
6996         5, 1, 2,
6997         5, 0, 3,
6998         5, 3, 1,
6999         0, 2, 4,
7000         2, 1, 4,
7001         3, 0, 4,
7002         1, 3, 4
7003 };
7004
7005 static const unsigned short nomodelelement3s[24] =
7006 {
7007         5, 2, 0,
7008         5, 1, 2,
7009         5, 0, 3,
7010         5, 3, 1,
7011         0, 2, 4,
7012         2, 1, 4,
7013         3, 0, 4,
7014         1, 3, 4
7015 };
7016
7017 static const float nomodelvertex3f[6*3] =
7018 {
7019         -16,   0,   0,
7020          16,   0,   0,
7021           0, -16,   0,
7022           0,  16,   0,
7023           0,   0, -16,
7024           0,   0,  16
7025 };
7026
7027 static const float nomodelcolor4f[6*4] =
7028 {
7029         0.0f, 0.0f, 0.5f, 1.0f,
7030         0.0f, 0.0f, 0.5f, 1.0f,
7031         0.0f, 0.5f, 0.0f, 1.0f,
7032         0.0f, 0.5f, 0.0f, 1.0f,
7033         0.5f, 0.0f, 0.0f, 1.0f,
7034         0.5f, 0.0f, 0.0f, 1.0f
7035 };
7036
7037 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7038 {
7039         int i;
7040         float f1, f2, *c;
7041         float color4f[6*4];
7042
7043         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);
7044
7045         // this is only called once per entity so numsurfaces is always 1, and
7046         // surfacelist is always {0}, so this code does not handle batches
7047
7048         if (rsurface.ent_flags & RENDER_ADDITIVE)
7049         {
7050                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7051                 GL_DepthMask(false);
7052         }
7053         else if (rsurface.colormod[3] < 1)
7054         {
7055                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7056                 GL_DepthMask(false);
7057         }
7058         else
7059         {
7060                 GL_BlendFunc(GL_ONE, GL_ZERO);
7061                 GL_DepthMask(true);
7062         }
7063         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7064         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7065         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7066         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7067         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7068         for (i = 0, c = color4f;i < 6;i++, c += 4)
7069         {
7070                 c[0] *= rsurface.colormod[0];
7071                 c[1] *= rsurface.colormod[1];
7072                 c[2] *= rsurface.colormod[2];
7073                 c[3] *= rsurface.colormod[3];
7074         }
7075         if (r_refdef.fogenabled)
7076         {
7077                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7078                 {
7079                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7080                         f2 = 1 - f1;
7081                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7082                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7083                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7084                 }
7085         }
7086 //      R_Mesh_ResetTextureState();
7087         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7088         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7089         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7090 }
7091
7092 void R_DrawNoModel(entity_render_t *ent)
7093 {
7094         vec3_t org;
7095         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7096         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7097                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7098         else
7099                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7100 }
7101
7102 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7103 {
7104         vec3_t right1, right2, diff, normal;
7105
7106         VectorSubtract (org2, org1, normal);
7107
7108         // calculate 'right' vector for start
7109         VectorSubtract (r_refdef.view.origin, org1, diff);
7110         CrossProduct (normal, diff, right1);
7111         VectorNormalize (right1);
7112
7113         // calculate 'right' vector for end
7114         VectorSubtract (r_refdef.view.origin, org2, diff);
7115         CrossProduct (normal, diff, right2);
7116         VectorNormalize (right2);
7117
7118         vert[ 0] = org1[0] + width * right1[0];
7119         vert[ 1] = org1[1] + width * right1[1];
7120         vert[ 2] = org1[2] + width * right1[2];
7121         vert[ 3] = org1[0] - width * right1[0];
7122         vert[ 4] = org1[1] - width * right1[1];
7123         vert[ 5] = org1[2] - width * right1[2];
7124         vert[ 6] = org2[0] - width * right2[0];
7125         vert[ 7] = org2[1] - width * right2[1];
7126         vert[ 8] = org2[2] - width * right2[2];
7127         vert[ 9] = org2[0] + width * right2[0];
7128         vert[10] = org2[1] + width * right2[1];
7129         vert[11] = org2[2] + width * right2[2];
7130 }
7131
7132 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)
7133 {
7134         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7135         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7136         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7137         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7138         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7139         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7140         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7141         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7142         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7143         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7144         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7145         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7146 }
7147
7148 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7149 {
7150         int i;
7151         float *vertex3f;
7152         float v[3];
7153         VectorSet(v, x, y, z);
7154         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7155                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7156                         break;
7157         if (i == mesh->numvertices)
7158         {
7159                 if (mesh->numvertices < mesh->maxvertices)
7160                 {
7161                         VectorCopy(v, vertex3f);
7162                         mesh->numvertices++;
7163                 }
7164                 return mesh->numvertices;
7165         }
7166         else
7167                 return i;
7168 }
7169
7170 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7171 {
7172         int i;
7173         int *e, element[3];
7174         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7175         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7176         e = mesh->element3i + mesh->numtriangles * 3;
7177         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7178         {
7179                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7180                 if (mesh->numtriangles < mesh->maxtriangles)
7181                 {
7182                         *e++ = element[0];
7183                         *e++ = element[1];
7184                         *e++ = element[2];
7185                         mesh->numtriangles++;
7186                 }
7187                 element[1] = element[2];
7188         }
7189 }
7190
7191 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7192 {
7193         int i;
7194         int *e, element[3];
7195         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7196         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7197         e = mesh->element3i + mesh->numtriangles * 3;
7198         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7199         {
7200                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7201                 if (mesh->numtriangles < mesh->maxtriangles)
7202                 {
7203                         *e++ = element[0];
7204                         *e++ = element[1];
7205                         *e++ = element[2];
7206                         mesh->numtriangles++;
7207                 }
7208                 element[1] = element[2];
7209         }
7210 }
7211
7212 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7213 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7214 {
7215         int planenum, planenum2;
7216         int w;
7217         int tempnumpoints;
7218         mplane_t *plane, *plane2;
7219         double maxdist;
7220         double temppoints[2][256*3];
7221         // figure out how large a bounding box we need to properly compute this brush
7222         maxdist = 0;
7223         for (w = 0;w < numplanes;w++)
7224                 maxdist = max(maxdist, fabs(planes[w].dist));
7225         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7226         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7227         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7228         {
7229                 w = 0;
7230                 tempnumpoints = 4;
7231                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7232                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7233                 {
7234                         if (planenum2 == planenum)
7235                                 continue;
7236                         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);
7237                         w = !w;
7238                 }
7239                 if (tempnumpoints < 3)
7240                         continue;
7241                 // generate elements forming a triangle fan for this polygon
7242                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7243         }
7244 }
7245
7246 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)
7247 {
7248         texturelayer_t *layer;
7249         layer = t->currentlayers + t->currentnumlayers++;
7250         layer->type = type;
7251         layer->depthmask = depthmask;
7252         layer->blendfunc1 = blendfunc1;
7253         layer->blendfunc2 = blendfunc2;
7254         layer->texture = texture;
7255         layer->texmatrix = *matrix;
7256         layer->color[0] = r;
7257         layer->color[1] = g;
7258         layer->color[2] = b;
7259         layer->color[3] = a;
7260 }
7261
7262 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7263 {
7264         if(parms[0] == 0 && parms[1] == 0)
7265                 return false;
7266         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7267                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7268                         return false;
7269         return true;
7270 }
7271
7272 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7273 {
7274         double index, f;
7275         index = parms[2] + r_refdef.scene.time * parms[3];
7276         index -= floor(index);
7277         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7278         {
7279         default:
7280         case Q3WAVEFUNC_NONE:
7281         case Q3WAVEFUNC_NOISE:
7282         case Q3WAVEFUNC_COUNT:
7283                 f = 0;
7284                 break;
7285         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7286         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7287         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7288         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7289         case Q3WAVEFUNC_TRIANGLE:
7290                 index *= 4;
7291                 f = index - floor(index);
7292                 if (index < 1)
7293                         f = f;
7294                 else if (index < 2)
7295                         f = 1 - f;
7296                 else if (index < 3)
7297                         f = -f;
7298                 else
7299                         f = -(1 - f);
7300                 break;
7301         }
7302         f = parms[0] + parms[1] * f;
7303         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7304                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7305         return (float) f;
7306 }
7307
7308 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7309 {
7310         int w, h, idx;
7311         float f;
7312         float tcmat[12];
7313         matrix4x4_t matrix, temp;
7314         switch(tcmod->tcmod)
7315         {
7316                 case Q3TCMOD_COUNT:
7317                 case Q3TCMOD_NONE:
7318                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7319                                 matrix = r_waterscrollmatrix;
7320                         else
7321                                 matrix = identitymatrix;
7322                         break;
7323                 case Q3TCMOD_ENTITYTRANSLATE:
7324                         // this is used in Q3 to allow the gamecode to control texcoord
7325                         // scrolling on the entity, which is not supported in darkplaces yet.
7326                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7327                         break;
7328                 case Q3TCMOD_ROTATE:
7329                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7330                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7331                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7332                         break;
7333                 case Q3TCMOD_SCALE:
7334                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7335                         break;
7336                 case Q3TCMOD_SCROLL:
7337                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7338                         break;
7339                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7340                         w = (int) tcmod->parms[0];
7341                         h = (int) tcmod->parms[1];
7342                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7343                         f = f - floor(f);
7344                         idx = (int) floor(f * w * h);
7345                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7346                         break;
7347                 case Q3TCMOD_STRETCH:
7348                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7349                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7350                         break;
7351                 case Q3TCMOD_TRANSFORM:
7352                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7353                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7354                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7355                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7356                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7357                         break;
7358                 case Q3TCMOD_TURBULENT:
7359                         // this is handled in the RSurf_PrepareVertices function
7360                         matrix = identitymatrix;
7361                         break;
7362         }
7363         temp = *texmatrix;
7364         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7365 }
7366
7367 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7368 {
7369         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7370         char name[MAX_QPATH];
7371         skinframe_t *skinframe;
7372         unsigned char pixels[296*194];
7373         strlcpy(cache->name, skinname, sizeof(cache->name));
7374         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7375         if (developer_loading.integer)
7376                 Con_Printf("loading %s\n", name);
7377         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7378         if (!skinframe || !skinframe->base)
7379         {
7380                 unsigned char *f;
7381                 fs_offset_t filesize;
7382                 skinframe = NULL;
7383                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7384                 if (f)
7385                 {
7386                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7387                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7388                         Mem_Free(f);
7389                 }
7390         }
7391         cache->skinframe = skinframe;
7392 }
7393
7394 texture_t *R_GetCurrentTexture(texture_t *t)
7395 {
7396         int i;
7397         const entity_render_t *ent = rsurface.entity;
7398         dp_model_t *model = ent->model;
7399         q3shaderinfo_layer_tcmod_t *tcmod;
7400
7401         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7402                 return t->currentframe;
7403         t->update_lastrenderframe = r_textureframe;
7404         t->update_lastrenderentity = (void *)ent;
7405
7406         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7407                 t->camera_entity = ent->entitynumber;
7408         else
7409                 t->camera_entity = 0;
7410
7411         // switch to an alternate material if this is a q1bsp animated material
7412         {
7413                 texture_t *texture = t;
7414                 int s = rsurface.ent_skinnum;
7415                 if ((unsigned int)s >= (unsigned int)model->numskins)
7416                         s = 0;
7417                 if (model->skinscenes)
7418                 {
7419                         if (model->skinscenes[s].framecount > 1)
7420                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7421                         else
7422                                 s = model->skinscenes[s].firstframe;
7423                 }
7424                 if (s > 0)
7425                         t = t + s * model->num_surfaces;
7426                 if (t->animated)
7427                 {
7428                         // use an alternate animation if the entity's frame is not 0,
7429                         // and only if the texture has an alternate animation
7430                         if (rsurface.ent_alttextures && t->anim_total[1])
7431                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7432                         else
7433                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7434                 }
7435                 texture->currentframe = t;
7436         }
7437
7438         // update currentskinframe to be a qw skin or animation frame
7439         if (rsurface.ent_qwskin >= 0)
7440         {
7441                 i = rsurface.ent_qwskin;
7442                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7443                 {
7444                         r_qwskincache_size = cl.maxclients;
7445                         if (r_qwskincache)
7446                                 Mem_Free(r_qwskincache);
7447                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7448                 }
7449                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7450                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7451                 t->currentskinframe = r_qwskincache[i].skinframe;
7452                 if (t->currentskinframe == NULL)
7453                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7454         }
7455         else if (t->numskinframes >= 2)
7456                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7457         if (t->backgroundnumskinframes >= 2)
7458                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7459
7460         t->currentmaterialflags = t->basematerialflags;
7461         t->currentalpha = rsurface.colormod[3];
7462         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7463                 t->currentalpha *= r_wateralpha.value;
7464         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7465                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7466         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7467                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7468         if (!(rsurface.ent_flags & RENDER_LIGHT))
7469                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7470         else if (FAKELIGHT_ENABLED)
7471         {
7472                         // no modellight if using fakelight for the map
7473         }
7474         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7475         {
7476                 // pick a model lighting mode
7477                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7478                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7479                 else
7480                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7481         }
7482         if (rsurface.ent_flags & RENDER_ADDITIVE)
7483                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7484         else if (t->currentalpha < 1)
7485                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7486         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7487                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7488         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7489                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7490         if (t->backgroundnumskinframes)
7491                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7492         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7493         {
7494                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7495                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7496         }
7497         else
7498                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7499         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7500                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7501
7502         // there is no tcmod
7503         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7504         {
7505                 t->currenttexmatrix = r_waterscrollmatrix;
7506                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7507         }
7508         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7509         {
7510                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7511                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7512         }
7513
7514         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7515                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7516         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7517                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7518
7519         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7520         if (t->currentskinframe->qpixels)
7521                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7522         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7523         if (!t->basetexture)
7524                 t->basetexture = r_texture_notexture;
7525         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7526         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7527         t->nmaptexture = t->currentskinframe->nmap;
7528         if (!t->nmaptexture)
7529                 t->nmaptexture = r_texture_blanknormalmap;
7530         t->glosstexture = r_texture_black;
7531         t->glowtexture = t->currentskinframe->glow;
7532         t->fogtexture = t->currentskinframe->fog;
7533         t->reflectmasktexture = t->currentskinframe->reflect;
7534         if (t->backgroundnumskinframes)
7535         {
7536                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7537                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7538                 t->backgroundglosstexture = r_texture_black;
7539                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7540                 if (!t->backgroundnmaptexture)
7541                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7542         }
7543         else
7544         {
7545                 t->backgroundbasetexture = r_texture_white;
7546                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7547                 t->backgroundglosstexture = r_texture_black;
7548                 t->backgroundglowtexture = NULL;
7549         }
7550         t->specularpower = r_shadow_glossexponent.value;
7551         // TODO: store reference values for these in the texture?
7552         t->specularscale = 0;
7553         if (r_shadow_gloss.integer > 0)
7554         {
7555                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7556                 {
7557                         if (r_shadow_glossintensity.value > 0)
7558                         {
7559                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7560                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7561                                 t->specularscale = r_shadow_glossintensity.value;
7562                         }
7563                 }
7564                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7565                 {
7566                         t->glosstexture = r_texture_white;
7567                         t->backgroundglosstexture = r_texture_white;
7568                         t->specularscale = r_shadow_gloss2intensity.value;
7569                         t->specularpower = r_shadow_gloss2exponent.value;
7570                 }
7571         }
7572         t->specularscale *= t->specularscalemod;
7573         t->specularpower *= t->specularpowermod;
7574
7575         // lightmaps mode looks bad with dlights using actual texturing, so turn
7576         // off the colormap and glossmap, but leave the normalmap on as it still
7577         // accurately represents the shading involved
7578         if (gl_lightmaps.integer)
7579         {
7580                 t->basetexture = r_texture_grey128;
7581                 t->pantstexture = r_texture_black;
7582                 t->shirttexture = r_texture_black;
7583                 t->nmaptexture = r_texture_blanknormalmap;
7584                 t->glosstexture = r_texture_black;
7585                 t->glowtexture = NULL;
7586                 t->fogtexture = NULL;
7587                 t->reflectmasktexture = NULL;
7588                 t->backgroundbasetexture = NULL;
7589                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7590                 t->backgroundglosstexture = r_texture_black;
7591                 t->backgroundglowtexture = NULL;
7592                 t->specularscale = 0;
7593                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7594         }
7595
7596         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7597         VectorClear(t->dlightcolor);
7598         t->currentnumlayers = 0;
7599         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7600         {
7601                 int blendfunc1, blendfunc2;
7602                 qboolean depthmask;
7603                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7604                 {
7605                         blendfunc1 = GL_SRC_ALPHA;
7606                         blendfunc2 = GL_ONE;
7607                 }
7608                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7609                 {
7610                         blendfunc1 = GL_SRC_ALPHA;
7611                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7612                 }
7613                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7614                 {
7615                         blendfunc1 = t->customblendfunc[0];
7616                         blendfunc2 = t->customblendfunc[1];
7617                 }
7618                 else
7619                 {
7620                         blendfunc1 = GL_ONE;
7621                         blendfunc2 = GL_ZERO;
7622                 }
7623                 // don't colormod evilblend textures
7624                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
7625                         VectorSet(t->lightmapcolor, 1, 1, 1);
7626                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7627                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7628                 {
7629                         // fullbright is not affected by r_refdef.lightmapintensity
7630                         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]);
7631                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7632                                 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]);
7633                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7634                                 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]);
7635                 }
7636                 else
7637                 {
7638                         vec3_t ambientcolor;
7639                         float colorscale;
7640                         // set the color tint used for lights affecting this surface
7641                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7642                         colorscale = 2;
7643                         // q3bsp has no lightmap updates, so the lightstylevalue that
7644                         // would normally be baked into the lightmap must be
7645                         // applied to the color
7646                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7647                         if (model->type == mod_brushq3)
7648                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7649                         colorscale *= r_refdef.lightmapintensity;
7650                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7651                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7652                         // basic lit geometry
7653                         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]);
7654                         // add pants/shirt if needed
7655                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7656                                 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]);
7657                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7658                                 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]);
7659                         // now add ambient passes if needed
7660                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7661                         {
7662                                 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]);
7663                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7664                                         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]);
7665                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7666                                         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]);
7667                         }
7668                 }
7669                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7670                         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]);
7671                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7672                 {
7673                         // if this is opaque use alpha blend which will darken the earlier
7674                         // passes cheaply.
7675                         //
7676                         // if this is an alpha blended material, all the earlier passes
7677                         // were darkened by fog already, so we only need to add the fog
7678                         // color ontop through the fog mask texture
7679                         //
7680                         // if this is an additive blended material, all the earlier passes
7681                         // were darkened by fog already, and we should not add fog color
7682                         // (because the background was not darkened, there is no fog color
7683                         // that was lost behind it).
7684                         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]);
7685                 }
7686         }
7687
7688         return t->currentframe;
7689 }
7690
7691 rsurfacestate_t rsurface;
7692
7693 void RSurf_ActiveWorldEntity(void)
7694 {
7695         dp_model_t *model = r_refdef.scene.worldmodel;
7696         //if (rsurface.entity == r_refdef.scene.worldentity)
7697         //      return;
7698         rsurface.entity = r_refdef.scene.worldentity;
7699         rsurface.skeleton = NULL;
7700         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7701         rsurface.ent_skinnum = 0;
7702         rsurface.ent_qwskin = -1;
7703         rsurface.ent_shadertime = 0;
7704         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7705         rsurface.matrix = identitymatrix;
7706         rsurface.inversematrix = identitymatrix;
7707         rsurface.matrixscale = 1;
7708         rsurface.inversematrixscale = 1;
7709         R_EntityMatrix(&identitymatrix);
7710         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7711         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7712         rsurface.fograngerecip = r_refdef.fograngerecip;
7713         rsurface.fogheightfade = r_refdef.fogheightfade;
7714         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7715         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7716         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7717         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7718         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7719         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7720         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7721         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7722         rsurface.colormod[3] = 1;
7723         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);
7724         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7725         rsurface.frameblend[0].lerp = 1;
7726         rsurface.ent_alttextures = false;
7727         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7728         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7729         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7730         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7731         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7732         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7733         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7734         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7735         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7736         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7737         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7738         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7739         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7740         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7741         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7742         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7743         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7744         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7745         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7746         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7747         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7748         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7749         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7750         rsurface.modelelement3i = model->surfmesh.data_element3i;
7751         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7752         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7753         rsurface.modelelement3s = model->surfmesh.data_element3s;
7754         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7755         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7756         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7757         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7758         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7759         rsurface.modelsurfaces = model->data_surfaces;
7760         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7761         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7762         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7763         rsurface.modelgeneratedvertex = false;
7764         rsurface.batchgeneratedvertex = false;
7765         rsurface.batchfirstvertex = 0;
7766         rsurface.batchnumvertices = 0;
7767         rsurface.batchfirsttriangle = 0;
7768         rsurface.batchnumtriangles = 0;
7769         rsurface.batchvertex3f  = NULL;
7770         rsurface.batchvertex3f_vertexbuffer = NULL;
7771         rsurface.batchvertex3f_bufferoffset = 0;
7772         rsurface.batchsvector3f = NULL;
7773         rsurface.batchsvector3f_vertexbuffer = NULL;
7774         rsurface.batchsvector3f_bufferoffset = 0;
7775         rsurface.batchtvector3f = NULL;
7776         rsurface.batchtvector3f_vertexbuffer = NULL;
7777         rsurface.batchtvector3f_bufferoffset = 0;
7778         rsurface.batchnormal3f  = NULL;
7779         rsurface.batchnormal3f_vertexbuffer = NULL;
7780         rsurface.batchnormal3f_bufferoffset = 0;
7781         rsurface.batchlightmapcolor4f = NULL;
7782         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7783         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7784         rsurface.batchtexcoordtexture2f = NULL;
7785         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7786         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7787         rsurface.batchtexcoordlightmap2f = NULL;
7788         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7789         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7790         rsurface.batchvertexmesh = NULL;
7791         rsurface.batchvertexmeshbuffer = NULL;
7792         rsurface.batchvertex3fbuffer = NULL;
7793         rsurface.batchelement3i = NULL;
7794         rsurface.batchelement3i_indexbuffer = NULL;
7795         rsurface.batchelement3i_bufferoffset = 0;
7796         rsurface.batchelement3s = NULL;
7797         rsurface.batchelement3s_indexbuffer = NULL;
7798         rsurface.batchelement3s_bufferoffset = 0;
7799         rsurface.passcolor4f = NULL;
7800         rsurface.passcolor4f_vertexbuffer = NULL;
7801         rsurface.passcolor4f_bufferoffset = 0;
7802 }
7803
7804 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7805 {
7806         dp_model_t *model = ent->model;
7807         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7808         //      return;
7809         rsurface.entity = (entity_render_t *)ent;
7810         rsurface.skeleton = ent->skeleton;
7811         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7812         rsurface.ent_skinnum = ent->skinnum;
7813         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;
7814         rsurface.ent_shadertime = ent->shadertime;
7815         rsurface.ent_flags = ent->flags;
7816         rsurface.matrix = ent->matrix;
7817         rsurface.inversematrix = ent->inversematrix;
7818         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7819         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7820         R_EntityMatrix(&rsurface.matrix);
7821         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7822         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7823         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7824         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7825         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7826         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7827         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7828         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7829         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7830         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7831         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7832         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7833         rsurface.colormod[3] = ent->alpha;
7834         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7835         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7836         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7837         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7838         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7839         if (ent->model->brush.submodel && !prepass)
7840         {
7841                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7842                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7843         }
7844         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7845         {
7846                 if (ent->animcache_vertex3f)
7847                 {
7848                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7849                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7850                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7851                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7852                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7853                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7854                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7855                 }
7856                 else if (wanttangents)
7857                 {
7858                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7859                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7860                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7861                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7862                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7863                         rsurface.modelvertexmesh = NULL;
7864                         rsurface.modelvertexmeshbuffer = NULL;
7865                         rsurface.modelvertex3fbuffer = NULL;
7866                 }
7867                 else if (wantnormals)
7868                 {
7869                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7870                         rsurface.modelsvector3f = NULL;
7871                         rsurface.modeltvector3f = NULL;
7872                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7873                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7874                         rsurface.modelvertexmesh = NULL;
7875                         rsurface.modelvertexmeshbuffer = NULL;
7876                         rsurface.modelvertex3fbuffer = NULL;
7877                 }
7878                 else
7879                 {
7880                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7881                         rsurface.modelsvector3f = NULL;
7882                         rsurface.modeltvector3f = NULL;
7883                         rsurface.modelnormal3f = NULL;
7884                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7885                         rsurface.modelvertexmesh = NULL;
7886                         rsurface.modelvertexmeshbuffer = NULL;
7887                         rsurface.modelvertex3fbuffer = NULL;
7888                 }
7889                 rsurface.modelvertex3f_vertexbuffer = 0;
7890                 rsurface.modelvertex3f_bufferoffset = 0;
7891                 rsurface.modelsvector3f_vertexbuffer = 0;
7892                 rsurface.modelsvector3f_bufferoffset = 0;
7893                 rsurface.modeltvector3f_vertexbuffer = 0;
7894                 rsurface.modeltvector3f_bufferoffset = 0;
7895                 rsurface.modelnormal3f_vertexbuffer = 0;
7896                 rsurface.modelnormal3f_bufferoffset = 0;
7897                 rsurface.modelgeneratedvertex = true;
7898         }
7899         else
7900         {
7901                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7902                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7903                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7904                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7905                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7906                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7907                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7908                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7909                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7910                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7911                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7912                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7913                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7914                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7915                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7916                 rsurface.modelgeneratedvertex = false;
7917         }
7918         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7919         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7921         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7922         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7923         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7924         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7925         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7926         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7927         rsurface.modelelement3i = model->surfmesh.data_element3i;
7928         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7929         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7930         rsurface.modelelement3s = model->surfmesh.data_element3s;
7931         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7932         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7933         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7934         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7935         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7936         rsurface.modelsurfaces = model->data_surfaces;
7937         rsurface.batchgeneratedvertex = false;
7938         rsurface.batchfirstvertex = 0;
7939         rsurface.batchnumvertices = 0;
7940         rsurface.batchfirsttriangle = 0;
7941         rsurface.batchnumtriangles = 0;
7942         rsurface.batchvertex3f  = NULL;
7943         rsurface.batchvertex3f_vertexbuffer = NULL;
7944         rsurface.batchvertex3f_bufferoffset = 0;
7945         rsurface.batchsvector3f = NULL;
7946         rsurface.batchsvector3f_vertexbuffer = NULL;
7947         rsurface.batchsvector3f_bufferoffset = 0;
7948         rsurface.batchtvector3f = NULL;
7949         rsurface.batchtvector3f_vertexbuffer = NULL;
7950         rsurface.batchtvector3f_bufferoffset = 0;
7951         rsurface.batchnormal3f  = NULL;
7952         rsurface.batchnormal3f_vertexbuffer = NULL;
7953         rsurface.batchnormal3f_bufferoffset = 0;
7954         rsurface.batchlightmapcolor4f = NULL;
7955         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7956         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7957         rsurface.batchtexcoordtexture2f = NULL;
7958         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7959         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7960         rsurface.batchtexcoordlightmap2f = NULL;
7961         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7962         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7963         rsurface.batchvertexmesh = NULL;
7964         rsurface.batchvertexmeshbuffer = NULL;
7965         rsurface.batchvertex3fbuffer = NULL;
7966         rsurface.batchelement3i = NULL;
7967         rsurface.batchelement3i_indexbuffer = NULL;
7968         rsurface.batchelement3i_bufferoffset = 0;
7969         rsurface.batchelement3s = NULL;
7970         rsurface.batchelement3s_indexbuffer = NULL;
7971         rsurface.batchelement3s_bufferoffset = 0;
7972         rsurface.passcolor4f = NULL;
7973         rsurface.passcolor4f_vertexbuffer = NULL;
7974         rsurface.passcolor4f_bufferoffset = 0;
7975 }
7976
7977 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)
7978 {
7979         rsurface.entity = r_refdef.scene.worldentity;
7980         rsurface.skeleton = NULL;
7981         rsurface.ent_skinnum = 0;
7982         rsurface.ent_qwskin = -1;
7983         rsurface.ent_shadertime = shadertime;
7984         rsurface.ent_flags = entflags;
7985         rsurface.modelnumvertices = numvertices;
7986         rsurface.modelnumtriangles = numtriangles;
7987         rsurface.matrix = *matrix;
7988         rsurface.inversematrix = *inversematrix;
7989         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7990         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7991         R_EntityMatrix(&rsurface.matrix);
7992         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7993         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7994         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7995         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7996         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7997         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7998         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7999         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8000         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8001         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8002         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8003         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8004         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);
8005         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8006         rsurface.frameblend[0].lerp = 1;
8007         rsurface.ent_alttextures = false;
8008         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8009         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8010         if (wanttangents)
8011         {
8012                 rsurface.modelvertex3f = (float *)vertex3f;
8013                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8014                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8015                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8016         }
8017         else if (wantnormals)
8018         {
8019                 rsurface.modelvertex3f = (float *)vertex3f;
8020                 rsurface.modelsvector3f = NULL;
8021                 rsurface.modeltvector3f = NULL;
8022                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8023         }
8024         else
8025         {
8026                 rsurface.modelvertex3f = (float *)vertex3f;
8027                 rsurface.modelsvector3f = NULL;
8028                 rsurface.modeltvector3f = NULL;
8029                 rsurface.modelnormal3f = NULL;
8030         }
8031         rsurface.modelvertexmesh = NULL;
8032         rsurface.modelvertexmeshbuffer = NULL;
8033         rsurface.modelvertex3fbuffer = NULL;
8034         rsurface.modelvertex3f_vertexbuffer = 0;
8035         rsurface.modelvertex3f_bufferoffset = 0;
8036         rsurface.modelsvector3f_vertexbuffer = 0;
8037         rsurface.modelsvector3f_bufferoffset = 0;
8038         rsurface.modeltvector3f_vertexbuffer = 0;
8039         rsurface.modeltvector3f_bufferoffset = 0;
8040         rsurface.modelnormal3f_vertexbuffer = 0;
8041         rsurface.modelnormal3f_bufferoffset = 0;
8042         rsurface.modelgeneratedvertex = true;
8043         rsurface.modellightmapcolor4f  = (float *)color4f;
8044         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8045         rsurface.modellightmapcolor4f_bufferoffset = 0;
8046         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8047         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8048         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8049         rsurface.modeltexcoordlightmap2f  = NULL;
8050         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8051         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8052         rsurface.modelelement3i = (int *)element3i;
8053         rsurface.modelelement3i_indexbuffer = NULL;
8054         rsurface.modelelement3i_bufferoffset = 0;
8055         rsurface.modelelement3s = (unsigned short *)element3s;
8056         rsurface.modelelement3s_indexbuffer = NULL;
8057         rsurface.modelelement3s_bufferoffset = 0;
8058         rsurface.modellightmapoffsets = NULL;
8059         rsurface.modelsurfaces = NULL;
8060         rsurface.batchgeneratedvertex = false;
8061         rsurface.batchfirstvertex = 0;
8062         rsurface.batchnumvertices = 0;
8063         rsurface.batchfirsttriangle = 0;
8064         rsurface.batchnumtriangles = 0;
8065         rsurface.batchvertex3f  = NULL;
8066         rsurface.batchvertex3f_vertexbuffer = NULL;
8067         rsurface.batchvertex3f_bufferoffset = 0;
8068         rsurface.batchsvector3f = NULL;
8069         rsurface.batchsvector3f_vertexbuffer = NULL;
8070         rsurface.batchsvector3f_bufferoffset = 0;
8071         rsurface.batchtvector3f = NULL;
8072         rsurface.batchtvector3f_vertexbuffer = NULL;
8073         rsurface.batchtvector3f_bufferoffset = 0;
8074         rsurface.batchnormal3f  = NULL;
8075         rsurface.batchnormal3f_vertexbuffer = NULL;
8076         rsurface.batchnormal3f_bufferoffset = 0;
8077         rsurface.batchlightmapcolor4f = NULL;
8078         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8079         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8080         rsurface.batchtexcoordtexture2f = NULL;
8081         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8082         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8083         rsurface.batchtexcoordlightmap2f = NULL;
8084         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8085         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8086         rsurface.batchvertexmesh = NULL;
8087         rsurface.batchvertexmeshbuffer = NULL;
8088         rsurface.batchvertex3fbuffer = NULL;
8089         rsurface.batchelement3i = NULL;
8090         rsurface.batchelement3i_indexbuffer = NULL;
8091         rsurface.batchelement3i_bufferoffset = 0;
8092         rsurface.batchelement3s = NULL;
8093         rsurface.batchelement3s_indexbuffer = NULL;
8094         rsurface.batchelement3s_bufferoffset = 0;
8095         rsurface.passcolor4f = NULL;
8096         rsurface.passcolor4f_vertexbuffer = NULL;
8097         rsurface.passcolor4f_bufferoffset = 0;
8098
8099         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8100         {
8101                 if ((wantnormals || wanttangents) && !normal3f)
8102                 {
8103                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8104                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8105                 }
8106                 if (wanttangents && !svector3f)
8107                 {
8108                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8109                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8110                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8111                 }
8112         }
8113 }
8114
8115 float RSurf_FogPoint(const float *v)
8116 {
8117         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8118         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8119         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8120         float FogHeightFade = r_refdef.fogheightfade;
8121         float fogfrac;
8122         unsigned int fogmasktableindex;
8123         if (r_refdef.fogplaneviewabove)
8124                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8125         else
8126                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8127         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8128         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8129 }
8130
8131 float RSurf_FogVertex(const float *v)
8132 {
8133         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8134         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8135         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8136         float FogHeightFade = rsurface.fogheightfade;
8137         float fogfrac;
8138         unsigned int fogmasktableindex;
8139         if (r_refdef.fogplaneviewabove)
8140                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8141         else
8142                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8143         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8144         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8145 }
8146
8147 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8148 {
8149         int i;
8150         for (i = 0;i < numelements;i++)
8151                 outelement3i[i] = inelement3i[i] + adjust;
8152 }
8153
8154 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8155 extern cvar_t gl_vbo;
8156 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8157 {
8158         int deformindex;
8159         int firsttriangle;
8160         int numtriangles;
8161         int firstvertex;
8162         int endvertex;
8163         int numvertices;
8164         int surfacefirsttriangle;
8165         int surfacenumtriangles;
8166         int surfacefirstvertex;
8167         int surfaceendvertex;
8168         int surfacenumvertices;
8169         int batchnumvertices;
8170         int batchnumtriangles;
8171         int needsupdate;
8172         int i, j;
8173         qboolean gaps;
8174         qboolean dynamicvertex;
8175         float amplitude;
8176         float animpos;
8177         float scale;
8178         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8179         float waveparms[4];
8180         q3shaderinfo_deform_t *deform;
8181         const msurface_t *surface, *firstsurface;
8182         r_vertexmesh_t *vertexmesh;
8183         if (!texturenumsurfaces)
8184                 return;
8185         // find vertex range of this surface batch
8186         gaps = false;
8187         firstsurface = texturesurfacelist[0];
8188         firsttriangle = firstsurface->num_firsttriangle;
8189         batchnumvertices = 0;
8190         batchnumtriangles = 0;
8191         firstvertex = endvertex = firstsurface->num_firstvertex;
8192         for (i = 0;i < texturenumsurfaces;i++)
8193         {
8194                 surface = texturesurfacelist[i];
8195                 if (surface != firstsurface + i)
8196                         gaps = true;
8197                 surfacefirstvertex = surface->num_firstvertex;
8198                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8199                 surfacenumvertices = surface->num_vertices;
8200                 surfacenumtriangles = surface->num_triangles;
8201                 if (firstvertex > surfacefirstvertex)
8202                         firstvertex = surfacefirstvertex;
8203                 if (endvertex < surfaceendvertex)
8204                         endvertex = surfaceendvertex;
8205                 batchnumvertices += surfacenumvertices;
8206                 batchnumtriangles += surfacenumtriangles;
8207         }
8208
8209         // we now know the vertex range used, and if there are any gaps in it
8210         rsurface.batchfirstvertex = firstvertex;
8211         rsurface.batchnumvertices = endvertex - firstvertex;
8212         rsurface.batchfirsttriangle = firsttriangle;
8213         rsurface.batchnumtriangles = batchnumtriangles;
8214
8215         // this variable holds flags for which properties have been updated that
8216         // may require regenerating vertexmesh array...
8217         needsupdate = 0;
8218
8219         // check if any dynamic vertex processing must occur
8220         dynamicvertex = false;
8221
8222         // if there is a chance of animated vertex colors, it's a dynamic batch
8223         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8224         {
8225                 dynamicvertex = true;
8226                 batchneed |= BATCHNEED_NOGAPS;
8227                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8228         }
8229
8230         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8231         {
8232                 switch (deform->deform)
8233                 {
8234                 default:
8235                 case Q3DEFORM_PROJECTIONSHADOW:
8236                 case Q3DEFORM_TEXT0:
8237                 case Q3DEFORM_TEXT1:
8238                 case Q3DEFORM_TEXT2:
8239                 case Q3DEFORM_TEXT3:
8240                 case Q3DEFORM_TEXT4:
8241                 case Q3DEFORM_TEXT5:
8242                 case Q3DEFORM_TEXT6:
8243                 case Q3DEFORM_TEXT7:
8244                 case Q3DEFORM_NONE:
8245                         break;
8246                 case Q3DEFORM_AUTOSPRITE:
8247                         dynamicvertex = true;
8248                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8249                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8250                         break;
8251                 case Q3DEFORM_AUTOSPRITE2:
8252                         dynamicvertex = true;
8253                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8254                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8255                         break;
8256                 case Q3DEFORM_NORMAL:
8257                         dynamicvertex = true;
8258                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8259                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8260                         break;
8261                 case Q3DEFORM_WAVE:
8262                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8263                                 break; // if wavefunc is a nop, ignore this transform
8264                         dynamicvertex = true;
8265                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8266                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8267                         break;
8268                 case Q3DEFORM_BULGE:
8269                         dynamicvertex = true;
8270                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8272                         break;
8273                 case Q3DEFORM_MOVE:
8274                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8275                                 break; // if wavefunc is a nop, ignore this transform
8276                         dynamicvertex = true;
8277                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8278                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8279                         break;
8280                 }
8281         }
8282         switch(rsurface.texture->tcgen.tcgen)
8283         {
8284         default:
8285         case Q3TCGEN_TEXTURE:
8286                 break;
8287         case Q3TCGEN_LIGHTMAP:
8288                 dynamicvertex = true;
8289                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8290                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8291                 break;
8292         case Q3TCGEN_VECTOR:
8293                 dynamicvertex = true;
8294                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8295                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8296                 break;
8297         case Q3TCGEN_ENVIRONMENT:
8298                 dynamicvertex = true;
8299                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8300                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8301                 break;
8302         }
8303         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8304         {
8305                 dynamicvertex = true;
8306                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8307                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8308         }
8309
8310         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8311         {
8312                 dynamicvertex = true;
8313                 batchneed |= BATCHNEED_NOGAPS;
8314                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8315         }
8316
8317         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8318         {
8319                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8320                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8321                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8322                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8323                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8324                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8325                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8326         }
8327
8328         // when the model data has no vertex buffer (dynamic mesh), we need to
8329         // eliminate gaps
8330         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8331                 batchneed |= BATCHNEED_NOGAPS;
8332
8333         // if needsupdate, we have to do a dynamic vertex batch for sure
8334         if (needsupdate & batchneed)
8335                 dynamicvertex = true;
8336
8337         // see if we need to build vertexmesh from arrays
8338         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8339                 dynamicvertex = true;
8340
8341         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8342         // also some drivers strongly dislike firstvertex
8343         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8344                 dynamicvertex = true;
8345
8346         rsurface.batchvertex3f = rsurface.modelvertex3f;
8347         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8348         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8349         rsurface.batchsvector3f = rsurface.modelsvector3f;
8350         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8351         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8352         rsurface.batchtvector3f = rsurface.modeltvector3f;
8353         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8354         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8355         rsurface.batchnormal3f = rsurface.modelnormal3f;
8356         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8357         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8358         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8359         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8360         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8361         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8362         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8363         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8364         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8365         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8366         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8367         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8368         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8369         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8370         rsurface.batchelement3i = rsurface.modelelement3i;
8371         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8372         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8373         rsurface.batchelement3s = rsurface.modelelement3s;
8374         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8375         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8376
8377         // if any dynamic vertex processing has to occur in software, we copy the
8378         // entire surface list together before processing to rebase the vertices
8379         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8380         //
8381         // if any gaps exist and we do not have a static vertex buffer, we have to
8382         // copy the surface list together to avoid wasting upload bandwidth on the
8383         // vertices in the gaps.
8384         //
8385         // if gaps exist and we have a static vertex buffer, we still have to
8386         // combine the index buffer ranges into one dynamic index buffer.
8387         //
8388         // in all cases we end up with data that can be drawn in one call.
8389
8390         if (!dynamicvertex)
8391         {
8392                 // static vertex data, just set pointers...
8393                 rsurface.batchgeneratedvertex = false;
8394                 // if there are gaps, we want to build a combined index buffer,
8395                 // otherwise use the original static buffer with an appropriate offset
8396                 if (gaps)
8397                 {
8398                         // build a new triangle elements array for this batch
8399                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8400                         rsurface.batchfirsttriangle = 0;
8401                         numtriangles = 0;
8402                         for (i = 0;i < texturenumsurfaces;i++)
8403                         {
8404                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8405                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8406                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8407                                 numtriangles += surfacenumtriangles;
8408                         }
8409                         rsurface.batchelement3i_indexbuffer = NULL;
8410                         rsurface.batchelement3i_bufferoffset = 0;
8411                         rsurface.batchelement3s = NULL;
8412                         rsurface.batchelement3s_indexbuffer = NULL;
8413                         rsurface.batchelement3s_bufferoffset = 0;
8414                         if (endvertex <= 65536)
8415                         {
8416                                 // make a 16bit (unsigned short) index array if possible
8417                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8418                                 for (i = 0;i < numtriangles*3;i++)
8419                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8420                         }
8421                 }
8422                 return;
8423         }
8424
8425         // something needs software processing, do it for real...
8426         // we only directly handle separate array data in this case and then
8427         // generate interleaved data if needed...
8428         rsurface.batchgeneratedvertex = true;
8429
8430         // now copy the vertex data into a combined array and make an index array
8431         // (this is what Quake3 does all the time)
8432         //if (gaps || rsurface.batchfirstvertex)
8433         {
8434                 rsurface.batchvertex3fbuffer = NULL;
8435                 rsurface.batchvertexmesh = NULL;
8436                 rsurface.batchvertexmeshbuffer = NULL;
8437                 rsurface.batchvertex3f = NULL;
8438                 rsurface.batchvertex3f_vertexbuffer = NULL;
8439                 rsurface.batchvertex3f_bufferoffset = 0;
8440                 rsurface.batchsvector3f = NULL;
8441                 rsurface.batchsvector3f_vertexbuffer = NULL;
8442                 rsurface.batchsvector3f_bufferoffset = 0;
8443                 rsurface.batchtvector3f = NULL;
8444                 rsurface.batchtvector3f_vertexbuffer = NULL;
8445                 rsurface.batchtvector3f_bufferoffset = 0;
8446                 rsurface.batchnormal3f = NULL;
8447                 rsurface.batchnormal3f_vertexbuffer = NULL;
8448                 rsurface.batchnormal3f_bufferoffset = 0;
8449                 rsurface.batchlightmapcolor4f = NULL;
8450                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8451                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8452                 rsurface.batchtexcoordtexture2f = NULL;
8453                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8454                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8455                 rsurface.batchtexcoordlightmap2f = NULL;
8456                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8457                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8458                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8459                 rsurface.batchelement3i_indexbuffer = NULL;
8460                 rsurface.batchelement3i_bufferoffset = 0;
8461                 rsurface.batchelement3s = NULL;
8462                 rsurface.batchelement3s_indexbuffer = NULL;
8463                 rsurface.batchelement3s_bufferoffset = 0;
8464                 // we'll only be setting up certain arrays as needed
8465                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8466                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8467                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8468                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8469                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8470                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8471                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8472                 {
8473                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8474                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8475                 }
8476                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8477                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8478                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8479                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8480                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8481                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8482                 numvertices = 0;
8483                 numtriangles = 0;
8484                 for (i = 0;i < texturenumsurfaces;i++)
8485                 {
8486                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8487                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8488                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8489                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8490                         // copy only the data requested
8491                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8492                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8493                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8494                         {
8495                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8496                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8497                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8498                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8499                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8500                                 {
8501                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8502                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8503                                 }
8504                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8505                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8506                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8507                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8508                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8509                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8510                         }
8511                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8512                         numvertices += surfacenumvertices;
8513                         numtriangles += surfacenumtriangles;
8514                 }
8515
8516                 // generate a 16bit index array as well if possible
8517                 // (in general, dynamic batches fit)
8518                 if (numvertices <= 65536)
8519                 {
8520                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8521                         for (i = 0;i < numtriangles*3;i++)
8522                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8523                 }
8524
8525                 // since we've copied everything, the batch now starts at 0
8526                 rsurface.batchfirstvertex = 0;
8527                 rsurface.batchnumvertices = batchnumvertices;
8528                 rsurface.batchfirsttriangle = 0;
8529                 rsurface.batchnumtriangles = batchnumtriangles;
8530         }
8531
8532         // q1bsp surfaces rendered in vertex color mode have to have colors
8533         // calculated based on lightstyles
8534         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8535         {
8536                 // generate color arrays for the surfaces in this list
8537                 int c[4];
8538                 int scale;
8539                 int size3;
8540                 const int *offsets;
8541                 const unsigned char *lm;
8542                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8543                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8544                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8545                 numvertices = 0;
8546                 for (i = 0;i < texturenumsurfaces;i++)
8547                 {
8548                         surface = texturesurfacelist[i];
8549                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8550                         surfacenumvertices = surface->num_vertices;
8551                         if (surface->lightmapinfo->samples)
8552                         {
8553                                 for (j = 0;j < surfacenumvertices;j++)
8554                                 {
8555                                         lm = surface->lightmapinfo->samples + offsets[j];
8556                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8557                                         VectorScale(lm, scale, c);
8558                                         if (surface->lightmapinfo->styles[1] != 255)
8559                                         {
8560                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8561                                                 lm += size3;
8562                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8563                                                 VectorMA(c, scale, lm, c);
8564                                                 if (surface->lightmapinfo->styles[2] != 255)
8565                                                 {
8566                                                         lm += size3;
8567                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8568                                                         VectorMA(c, scale, lm, c);
8569                                                         if (surface->lightmapinfo->styles[3] != 255)
8570                                                         {
8571                                                                 lm += size3;
8572                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8573                                                                 VectorMA(c, scale, lm, c);
8574                                                         }
8575                                                 }
8576                                         }
8577                                         c[0] >>= 7;
8578                                         c[1] >>= 7;
8579                                         c[2] >>= 7;
8580                                         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);
8581                                         numvertices++;
8582                                 }
8583                         }
8584                         else
8585                         {
8586                                 for (j = 0;j < surfacenumvertices;j++)
8587                                 {
8588                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8589                                         numvertices++;
8590                                 }
8591                         }
8592                 }
8593         }
8594
8595         // if vertices are deformed (sprite flares and things in maps, possibly
8596         // water waves, bulges and other deformations), modify the copied vertices
8597         // in place
8598         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8599         {
8600                 switch (deform->deform)
8601                 {
8602                 default:
8603                 case Q3DEFORM_PROJECTIONSHADOW:
8604                 case Q3DEFORM_TEXT0:
8605                 case Q3DEFORM_TEXT1:
8606                 case Q3DEFORM_TEXT2:
8607                 case Q3DEFORM_TEXT3:
8608                 case Q3DEFORM_TEXT4:
8609                 case Q3DEFORM_TEXT5:
8610                 case Q3DEFORM_TEXT6:
8611                 case Q3DEFORM_TEXT7:
8612                 case Q3DEFORM_NONE:
8613                         break;
8614                 case Q3DEFORM_AUTOSPRITE:
8615                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8616                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8617                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8618                         VectorNormalize(newforward);
8619                         VectorNormalize(newright);
8620                         VectorNormalize(newup);
8621 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8622 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8623 //                      rsurface.batchvertex3f_bufferoffset = 0;
8624 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8625 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8626 //                      rsurface.batchsvector3f_bufferoffset = 0;
8627 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8628 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8629 //                      rsurface.batchtvector3f_bufferoffset = 0;
8630 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8631 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8632 //                      rsurface.batchnormal3f_bufferoffset = 0;
8633                         // a single autosprite surface can contain multiple sprites...
8634                         for (j = 0;j < batchnumvertices - 3;j += 4)
8635                         {
8636                                 VectorClear(center);
8637                                 for (i = 0;i < 4;i++)
8638                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8639                                 VectorScale(center, 0.25f, center);
8640                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8641                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8642                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8643                                 for (i = 0;i < 4;i++)
8644                                 {
8645                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8646                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8647                                 }
8648                         }
8649                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8650                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8651                         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);
8652                         break;
8653                 case Q3DEFORM_AUTOSPRITE2:
8654                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8655                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8656                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8657                         VectorNormalize(newforward);
8658                         VectorNormalize(newright);
8659                         VectorNormalize(newup);
8660 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8661 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8662 //                      rsurface.batchvertex3f_bufferoffset = 0;
8663                         {
8664                                 const float *v1, *v2;
8665                                 vec3_t start, end;
8666                                 float f, l;
8667                                 struct
8668                                 {
8669                                         float length2;
8670                                         const float *v1;
8671                                         const float *v2;
8672                                 }
8673                                 shortest[2];
8674                                 memset(shortest, 0, sizeof(shortest));
8675                                 // a single autosprite surface can contain multiple sprites...
8676                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8677                                 {
8678                                         VectorClear(center);
8679                                         for (i = 0;i < 4;i++)
8680                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8681                                         VectorScale(center, 0.25f, center);
8682                                         // find the two shortest edges, then use them to define the
8683                                         // axis vectors for rotating around the central axis
8684                                         for (i = 0;i < 6;i++)
8685                                         {
8686                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8687                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8688                                                 l = VectorDistance2(v1, v2);
8689                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8690                                                 if (v1[2] != v2[2])
8691                                                         l += (1.0f / 1024.0f);
8692                                                 if (shortest[0].length2 > l || i == 0)
8693                                                 {
8694                                                         shortest[1] = shortest[0];
8695                                                         shortest[0].length2 = l;
8696                                                         shortest[0].v1 = v1;
8697                                                         shortest[0].v2 = v2;
8698                                                 }
8699                                                 else if (shortest[1].length2 > l || i == 1)
8700                                                 {
8701                                                         shortest[1].length2 = l;
8702                                                         shortest[1].v1 = v1;
8703                                                         shortest[1].v2 = v2;
8704                                                 }
8705                                         }
8706                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8707                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8708                                         // this calculates the right vector from the shortest edge
8709                                         // and the up vector from the edge midpoints
8710                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8711                                         VectorNormalize(right);
8712                                         VectorSubtract(end, start, up);
8713                                         VectorNormalize(up);
8714                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8715                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8716                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8717                                         VectorNegate(forward, forward);
8718                                         VectorReflect(forward, 0, up, forward);
8719                                         VectorNormalize(forward);
8720                                         CrossProduct(up, forward, newright);
8721                                         VectorNormalize(newright);
8722                                         // rotate the quad around the up axis vector, this is made
8723                                         // especially easy by the fact we know the quad is flat,
8724                                         // so we only have to subtract the center position and
8725                                         // measure distance along the right vector, and then
8726                                         // multiply that by the newright vector and add back the
8727                                         // center position
8728                                         // we also need to subtract the old position to undo the
8729                                         // displacement from the center, which we do with a
8730                                         // DotProduct, the subtraction/addition of center is also
8731                                         // optimized into DotProducts here
8732                                         l = DotProduct(right, center);
8733                                         for (i = 0;i < 4;i++)
8734                                         {
8735                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8736                                                 f = DotProduct(right, v1) - l;
8737                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8738                                         }
8739                                 }
8740                         }
8741                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8742                         {
8743 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8744 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8745 //                              rsurface.batchnormal3f_bufferoffset = 0;
8746                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8747                         }
8748                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8749                         {
8750 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8751 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8752 //                              rsurface.batchsvector3f_bufferoffset = 0;
8753 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8754 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8755 //                              rsurface.batchtvector3f_bufferoffset = 0;
8756                                 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);
8757                         }
8758                         break;
8759                 case Q3DEFORM_NORMAL:
8760                         // deform the normals to make reflections wavey
8761                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8762                         rsurface.batchnormal3f_vertexbuffer = NULL;
8763                         rsurface.batchnormal3f_bufferoffset = 0;
8764                         for (j = 0;j < batchnumvertices;j++)
8765                         {
8766                                 float vertex[3];
8767                                 float *normal = rsurface.batchnormal3f + 3*j;
8768                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8769                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8770                                 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]);
8771                                 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]);
8772                                 VectorNormalize(normal);
8773                         }
8774                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8775                         {
8776 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8777 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8778 //                              rsurface.batchsvector3f_bufferoffset = 0;
8779 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8780 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8781 //                              rsurface.batchtvector3f_bufferoffset = 0;
8782                                 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);
8783                         }
8784                         break;
8785                 case Q3DEFORM_WAVE:
8786                         // deform vertex array to make wavey water and flags and such
8787                         waveparms[0] = deform->waveparms[0];
8788                         waveparms[1] = deform->waveparms[1];
8789                         waveparms[2] = deform->waveparms[2];
8790                         waveparms[3] = deform->waveparms[3];
8791                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8792                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8793                         // this is how a divisor of vertex influence on deformation
8794                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8795                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8796 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8797 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8798 //                      rsurface.batchvertex3f_bufferoffset = 0;
8799 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8800 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8801 //                      rsurface.batchnormal3f_bufferoffset = 0;
8802                         for (j = 0;j < batchnumvertices;j++)
8803                         {
8804                                 // if the wavefunc depends on time, evaluate it per-vertex
8805                                 if (waveparms[3])
8806                                 {
8807                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8808                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8809                                 }
8810                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8811                         }
8812                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8813                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8814                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8815                         {
8816 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8818 //                              rsurface.batchsvector3f_bufferoffset = 0;
8819 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8821 //                              rsurface.batchtvector3f_bufferoffset = 0;
8822                                 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);
8823                         }
8824                         break;
8825                 case Q3DEFORM_BULGE:
8826                         // deform vertex array to make the surface have moving bulges
8827 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8828 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8829 //                      rsurface.batchvertex3f_bufferoffset = 0;
8830 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8831 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8832 //                      rsurface.batchnormal3f_bufferoffset = 0;
8833                         for (j = 0;j < batchnumvertices;j++)
8834                         {
8835                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8836                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8837                         }
8838                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8839                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8840                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8841                         {
8842 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8843 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8844 //                              rsurface.batchsvector3f_bufferoffset = 0;
8845 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8846 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8847 //                              rsurface.batchtvector3f_bufferoffset = 0;
8848                                 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);
8849                         }
8850                         break;
8851                 case Q3DEFORM_MOVE:
8852                         // deform vertex array
8853                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8854                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8855                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8856                         VectorScale(deform->parms, scale, waveparms);
8857 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8858 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8859 //                      rsurface.batchvertex3f_bufferoffset = 0;
8860                         for (j = 0;j < batchnumvertices;j++)
8861                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8862                         break;
8863                 }
8864         }
8865
8866         // generate texcoords based on the chosen texcoord source
8867         switch(rsurface.texture->tcgen.tcgen)
8868         {
8869         default:
8870         case Q3TCGEN_TEXTURE:
8871                 break;
8872         case Q3TCGEN_LIGHTMAP:
8873 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8874 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8875 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8876                 if (rsurface.batchtexcoordlightmap2f)
8877                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8878                 break;
8879         case Q3TCGEN_VECTOR:
8880 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8881 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8882 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8883                 for (j = 0;j < batchnumvertices;j++)
8884                 {
8885                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8886                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8887                 }
8888                 break;
8889         case Q3TCGEN_ENVIRONMENT:
8890                 // make environment reflections using a spheremap
8891                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8892                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8893                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8894                 for (j = 0;j < batchnumvertices;j++)
8895                 {
8896                         // identical to Q3A's method, but executed in worldspace so
8897                         // carried models can be shiny too
8898
8899                         float viewer[3], d, reflected[3], worldreflected[3];
8900
8901                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8902                         // VectorNormalize(viewer);
8903
8904                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8905
8906                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8907                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8908                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8909                         // note: this is proportinal to viewer, so we can normalize later
8910
8911                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8912                         VectorNormalize(worldreflected);
8913
8914                         // note: this sphere map only uses world x and z!
8915                         // so positive and negative y will LOOK THE SAME.
8916                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8917                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8918                 }
8919                 break;
8920         }
8921         // the only tcmod that needs software vertex processing is turbulent, so
8922         // check for it here and apply the changes if needed
8923         // and we only support that as the first one
8924         // (handling a mixture of turbulent and other tcmods would be problematic
8925         //  without punting it entirely to a software path)
8926         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8927         {
8928                 amplitude = rsurface.texture->tcmods[0].parms[1];
8929                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8930 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8931 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8932 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8933                 for (j = 0;j < batchnumvertices;j++)
8934                 {
8935                         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);
8936                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8937                 }
8938         }
8939
8940         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8941         {
8942                 // convert the modified arrays to vertex structs
8943 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8944 //              rsurface.batchvertexmeshbuffer = NULL;
8945                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8946                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8947                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8948                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8949                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8950                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8951                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8952                 {
8953                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8954                         {
8955                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8956                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8957                         }
8958                 }
8959                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8960                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8961                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8962                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8963                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8964                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8965                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8966                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8967                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8968         }
8969 }
8970
8971 void RSurf_DrawBatch(void)
8972 {
8973         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8974         // through the pipeline, killing it earlier in the pipeline would have
8975         // per-surface overhead rather than per-batch overhead, so it's best to
8976         // reject it here, before it hits glDraw.
8977         if (rsurface.batchnumtriangles == 0)
8978                 return;
8979 #if 0
8980         // batch debugging code
8981         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8982         {
8983                 int i;
8984                 int j;
8985                 int c;
8986                 const int *e;
8987                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8988                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8989                 {
8990                         c = e[i];
8991                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8992                         {
8993                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8994                                 {
8995                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8996                                                 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);
8997                                         break;
8998                                 }
8999                         }
9000                 }
9001         }
9002 #endif
9003         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);
9004 }
9005
9006 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9007 {
9008         // pick the closest matching water plane
9009         int planeindex, vertexindex, bestplaneindex = -1;
9010         float d, bestd;
9011         vec3_t vert;
9012         const float *v;
9013         r_waterstate_waterplane_t *p;
9014         qboolean prepared = false;
9015         bestd = 0;
9016         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9017         {
9018                 if(p->camera_entity != rsurface.texture->camera_entity)
9019                         continue;
9020                 d = 0;
9021                 if(!prepared)
9022                 {
9023                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9024                         prepared = true;
9025                         if(rsurface.batchnumvertices == 0)
9026                                 break;
9027                 }
9028                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9029                 {
9030                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9031                         d += fabs(PlaneDiff(vert, &p->plane));
9032                 }
9033                 if (bestd > d || bestplaneindex < 0)
9034                 {
9035                         bestd = d;
9036                         bestplaneindex = planeindex;
9037                 }
9038         }
9039         return bestplaneindex;
9040         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9041         // this situation though, as it might be better to render single larger
9042         // batches with useless stuff (backface culled for example) than to
9043         // render multiple smaller batches
9044 }
9045
9046 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9047 {
9048         int i;
9049         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9050         rsurface.passcolor4f_vertexbuffer = 0;
9051         rsurface.passcolor4f_bufferoffset = 0;
9052         for (i = 0;i < rsurface.batchnumvertices;i++)
9053                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9054 }
9055
9056 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9057 {
9058         int i;
9059         float f;
9060         const float *v;
9061         const float *c;
9062         float *c2;
9063         if (rsurface.passcolor4f)
9064         {
9065                 // generate color arrays
9066                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9067                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9068                 rsurface.passcolor4f_vertexbuffer = 0;
9069                 rsurface.passcolor4f_bufferoffset = 0;
9070                 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)
9071                 {
9072                         f = RSurf_FogVertex(v);
9073                         c2[0] = c[0] * f;
9074                         c2[1] = c[1] * f;
9075                         c2[2] = c[2] * f;
9076                         c2[3] = c[3];
9077                 }
9078         }
9079         else
9080         {
9081                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9082                 rsurface.passcolor4f_vertexbuffer = 0;
9083                 rsurface.passcolor4f_bufferoffset = 0;
9084                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9085                 {
9086                         f = RSurf_FogVertex(v);
9087                         c2[0] = f;
9088                         c2[1] = f;
9089                         c2[2] = f;
9090                         c2[3] = 1;
9091                 }
9092         }
9093 }
9094
9095 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9096 {
9097         int i;
9098         float f;
9099         const float *v;
9100         const float *c;
9101         float *c2;
9102         if (!rsurface.passcolor4f)
9103                 return;
9104         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9105         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9106         rsurface.passcolor4f_vertexbuffer = 0;
9107         rsurface.passcolor4f_bufferoffset = 0;
9108         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)
9109         {
9110                 f = RSurf_FogVertex(v);
9111                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9112                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9113                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9114                 c2[3] = c[3];
9115         }
9116 }
9117
9118 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9119 {
9120         int i;
9121         const float *c;
9122         float *c2;
9123         if (!rsurface.passcolor4f)
9124                 return;
9125         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9126         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9127         rsurface.passcolor4f_vertexbuffer = 0;
9128         rsurface.passcolor4f_bufferoffset = 0;
9129         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9130         {
9131                 c2[0] = c[0] * r;
9132                 c2[1] = c[1] * g;
9133                 c2[2] = c[2] * b;
9134                 c2[3] = c[3] * a;
9135         }
9136 }
9137
9138 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9139 {
9140         int i;
9141         const float *c;
9142         float *c2;
9143         if (!rsurface.passcolor4f)
9144                 return;
9145         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9146         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9147         rsurface.passcolor4f_vertexbuffer = 0;
9148         rsurface.passcolor4f_bufferoffset = 0;
9149         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9150         {
9151                 c2[0] = c[0] + r_refdef.scene.ambient;
9152                 c2[1] = c[1] + r_refdef.scene.ambient;
9153                 c2[2] = c[2] + r_refdef.scene.ambient;
9154                 c2[3] = c[3];
9155         }
9156 }
9157
9158 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9159 {
9160         // TODO: optimize
9161         rsurface.passcolor4f = NULL;
9162         rsurface.passcolor4f_vertexbuffer = 0;
9163         rsurface.passcolor4f_bufferoffset = 0;
9164         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9165         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9166         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9167         GL_Color(r, g, b, a);
9168         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9169         RSurf_DrawBatch();
9170 }
9171
9172 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9173 {
9174         // TODO: optimize applyfog && applycolor case
9175         // just apply fog if necessary, and tint the fog color array if necessary
9176         rsurface.passcolor4f = NULL;
9177         rsurface.passcolor4f_vertexbuffer = 0;
9178         rsurface.passcolor4f_bufferoffset = 0;
9179         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9180         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9181         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9182         GL_Color(r, g, b, a);
9183         RSurf_DrawBatch();
9184 }
9185
9186 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9187 {
9188         // TODO: optimize
9189         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9190         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9191         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9192         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9193         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9194         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9195         GL_Color(r, g, b, a);
9196         RSurf_DrawBatch();
9197 }
9198
9199 static void RSurf_DrawBatch_GL11_ClampColor(void)
9200 {
9201         int i;
9202         const float *c1;
9203         float *c2;
9204         if (!rsurface.passcolor4f)
9205                 return;
9206         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9207         {
9208                 c2[0] = bound(0.0f, c1[0], 1.0f);
9209                 c2[1] = bound(0.0f, c1[1], 1.0f);
9210                 c2[2] = bound(0.0f, c1[2], 1.0f);
9211                 c2[3] = bound(0.0f, c1[3], 1.0f);
9212         }
9213 }
9214
9215 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9216 {
9217         int i;
9218         float f;
9219         const float *v;
9220         const float *n;
9221         float *c;
9222         //vec3_t eyedir;
9223
9224         // fake shading
9225         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9226         rsurface.passcolor4f_vertexbuffer = 0;
9227         rsurface.passcolor4f_bufferoffset = 0;
9228         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)
9229         {
9230                 f = -DotProduct(r_refdef.view.forward, n);
9231                 f = max(0, f);
9232                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9233                 f *= r_refdef.lightmapintensity;
9234                 Vector4Set(c, f, f, f, 1);
9235         }
9236 }
9237
9238 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9239 {
9240         RSurf_DrawBatch_GL11_ApplyFakeLight();
9241         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9242         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9243         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9244         GL_Color(r, g, b, a);
9245         RSurf_DrawBatch();
9246 }
9247
9248 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9249 {
9250         int i;
9251         float f;
9252         float alpha;
9253         const float *v;
9254         const float *n;
9255         float *c;
9256         vec3_t ambientcolor;
9257         vec3_t diffusecolor;
9258         vec3_t lightdir;
9259         // TODO: optimize
9260         // model lighting
9261         VectorCopy(rsurface.modellight_lightdir, lightdir);
9262         f = 0.5f * r_refdef.lightmapintensity;
9263         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9264         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9265         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9266         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9267         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9268         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9269         alpha = *a;
9270         if (VectorLength2(diffusecolor) > 0)
9271         {
9272                 // q3-style directional shading
9273                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9274                 rsurface.passcolor4f_vertexbuffer = 0;
9275                 rsurface.passcolor4f_bufferoffset = 0;
9276                 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)
9277                 {
9278                         if ((f = DotProduct(n, lightdir)) > 0)
9279                                 VectorMA(ambientcolor, f, diffusecolor, c);
9280                         else
9281                                 VectorCopy(ambientcolor, c);
9282                         c[3] = alpha;
9283                 }
9284                 *r = 1;
9285                 *g = 1;
9286                 *b = 1;
9287                 *a = 1;
9288                 *applycolor = false;
9289         }
9290         else
9291         {
9292                 *r = ambientcolor[0];
9293                 *g = ambientcolor[1];
9294                 *b = ambientcolor[2];
9295                 rsurface.passcolor4f = NULL;
9296                 rsurface.passcolor4f_vertexbuffer = 0;
9297                 rsurface.passcolor4f_bufferoffset = 0;
9298         }
9299 }
9300
9301 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9302 {
9303         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9304         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9305         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9306         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9307         GL_Color(r, g, b, a);
9308         RSurf_DrawBatch();
9309 }
9310
9311 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9312 {
9313         int i;
9314         float f;
9315         const float *v;
9316         float *c;
9317         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9318         {
9319                 f = 1 - RSurf_FogVertex(v);
9320                 c[0] = r;
9321                 c[1] = g;
9322                 c[2] = b;
9323                 c[3] = f * a;
9324         }
9325 }
9326
9327 void RSurf_SetupDepthAndCulling(void)
9328 {
9329         // submodels are biased to avoid z-fighting with world surfaces that they
9330         // may be exactly overlapping (avoids z-fighting artifacts on certain
9331         // doors and things in Quake maps)
9332         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9333         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9334         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9335         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9336 }
9337
9338 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9339 {
9340         // transparent sky would be ridiculous
9341         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9342                 return;
9343         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9344         skyrenderlater = true;
9345         RSurf_SetupDepthAndCulling();
9346         GL_DepthMask(true);
9347         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9348         // skymasking on them, and Quake3 never did sky masking (unlike
9349         // software Quake and software Quake2), so disable the sky masking
9350         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9351         // and skymasking also looks very bad when noclipping outside the
9352         // level, so don't use it then either.
9353         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9354         {
9355                 R_Mesh_ResetTextureState();
9356                 if (skyrendermasked)
9357                 {
9358                         R_SetupShader_DepthOrShadow();
9359                         // depth-only (masking)
9360                         GL_ColorMask(0,0,0,0);
9361                         // just to make sure that braindead drivers don't draw
9362                         // anything despite that colormask...
9363                         GL_BlendFunc(GL_ZERO, GL_ONE);
9364                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9365                         if (rsurface.batchvertex3fbuffer)
9366                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9367                         else
9368                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9369                 }
9370                 else
9371                 {
9372                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9373                         // fog sky
9374                         GL_BlendFunc(GL_ONE, GL_ZERO);
9375                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9376                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9377                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9378                 }
9379                 RSurf_DrawBatch();
9380                 if (skyrendermasked)
9381                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9382         }
9383         R_Mesh_ResetTextureState();
9384         GL_Color(1, 1, 1, 1);
9385 }
9386
9387 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9388 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9389 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9390 {
9391         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9392                 return;
9393         if (prepass)
9394         {
9395                 // render screenspace normalmap to texture
9396                 GL_DepthMask(true);
9397                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9398                 RSurf_DrawBatch();
9399                 return;
9400         }
9401
9402         // bind lightmap texture
9403
9404         // water/refraction/reflection/camera surfaces have to be handled specially
9405         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9406         {
9407                 int start, end, startplaneindex;
9408                 for (start = 0;start < texturenumsurfaces;start = end)
9409                 {
9410                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9411                         if(startplaneindex < 0)
9412                         {
9413                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9414                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9415                                 end = start + 1;
9416                                 continue;
9417                         }
9418                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9419                                 ;
9420                         // now that we have a batch using the same planeindex, render it
9421                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9422                         {
9423                                 // render water or distortion background
9424                                 GL_DepthMask(true);
9425                                 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));
9426                                 RSurf_DrawBatch();
9427                                 // blend surface on top
9428                                 GL_DepthMask(false);
9429                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9430                                 RSurf_DrawBatch();
9431                         }
9432                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9433                         {
9434                                 // render surface with reflection texture as input
9435                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9436                                 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));
9437                                 RSurf_DrawBatch();
9438                         }
9439                 }
9440                 return;
9441         }
9442
9443         // render surface batch normally
9444         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9445         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9446         RSurf_DrawBatch();
9447 }
9448
9449 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9450 {
9451         // OpenGL 1.3 path - anything not completely ancient
9452         qboolean applycolor;
9453         qboolean applyfog;
9454         int layerindex;
9455         const texturelayer_t *layer;
9456         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);
9457         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9458
9459         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9460         {
9461                 vec4_t layercolor;
9462                 int layertexrgbscale;
9463                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9464                 {
9465                         if (layerindex == 0)
9466                                 GL_AlphaTest(true);
9467                         else
9468                         {
9469                                 GL_AlphaTest(false);
9470                                 GL_DepthFunc(GL_EQUAL);
9471                         }
9472                 }
9473                 GL_DepthMask(layer->depthmask && writedepth);
9474                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9475                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9476                 {
9477                         layertexrgbscale = 4;
9478                         VectorScale(layer->color, 0.25f, layercolor);
9479                 }
9480                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9481                 {
9482                         layertexrgbscale = 2;
9483                         VectorScale(layer->color, 0.5f, layercolor);
9484                 }
9485                 else
9486                 {
9487                         layertexrgbscale = 1;
9488                         VectorScale(layer->color, 1.0f, layercolor);
9489                 }
9490                 layercolor[3] = layer->color[3];
9491                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9492                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9493                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9494                 switch (layer->type)
9495                 {
9496                 case TEXTURELAYERTYPE_LITTEXTURE:
9497                         // single-pass lightmapped texture with 2x rgbscale
9498                         R_Mesh_TexBind(0, r_texture_white);
9499                         R_Mesh_TexMatrix(0, NULL);
9500                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9501                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9502                         R_Mesh_TexBind(1, layer->texture);
9503                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9504                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9505                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9506                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9507                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9508                         else if (FAKELIGHT_ENABLED)
9509                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9510                         else if (rsurface.uselightmaptexture)
9511                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9512                         else
9513                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9514                         break;
9515                 case TEXTURELAYERTYPE_TEXTURE:
9516                         // singletexture unlit texture with transparency support
9517                         R_Mesh_TexBind(0, layer->texture);
9518                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9519                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9520                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9521                         R_Mesh_TexBind(1, 0);
9522                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9523                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9524                         break;
9525                 case TEXTURELAYERTYPE_FOG:
9526                         // singletexture fogging
9527                         if (layer->texture)
9528                         {
9529                                 R_Mesh_TexBind(0, layer->texture);
9530                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9531                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9532                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9533                         }
9534                         else
9535                         {
9536                                 R_Mesh_TexBind(0, 0);
9537                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9538                         }
9539                         R_Mesh_TexBind(1, 0);
9540                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9541                         // generate a color array for the fog pass
9542                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9543                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9544                         RSurf_DrawBatch();
9545                         break;
9546                 default:
9547                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9548                 }
9549         }
9550         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9551         {
9552                 GL_DepthFunc(GL_LEQUAL);
9553                 GL_AlphaTest(false);
9554         }
9555 }
9556
9557 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9558 {
9559         // OpenGL 1.1 - crusty old voodoo path
9560         qboolean applyfog;
9561         int layerindex;
9562         const texturelayer_t *layer;
9563         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);
9564         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9565
9566         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9567         {
9568                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9569                 {
9570                         if (layerindex == 0)
9571                                 GL_AlphaTest(true);
9572                         else
9573                         {
9574                                 GL_AlphaTest(false);
9575                                 GL_DepthFunc(GL_EQUAL);
9576                         }
9577                 }
9578                 GL_DepthMask(layer->depthmask && writedepth);
9579                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9580                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9581                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9582                 switch (layer->type)
9583                 {
9584                 case TEXTURELAYERTYPE_LITTEXTURE:
9585                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9586                         {
9587                                 // two-pass lit texture with 2x rgbscale
9588                                 // first the lightmap pass
9589                                 R_Mesh_TexBind(0, r_texture_white);
9590                                 R_Mesh_TexMatrix(0, NULL);
9591                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9592                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9593                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9594                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9595                                 else if (FAKELIGHT_ENABLED)
9596                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9597                                 else if (rsurface.uselightmaptexture)
9598                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9599                                 else
9600                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9601                                 // then apply the texture to it
9602                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9603                                 R_Mesh_TexBind(0, layer->texture);
9604                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9605                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9606                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9607                                 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);
9608                         }
9609                         else
9610                         {
9611                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9612                                 R_Mesh_TexBind(0, layer->texture);
9613                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9614                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9615                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9616                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9617                                         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);
9618                                 else
9619                                         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);
9620                         }
9621                         break;
9622                 case TEXTURELAYERTYPE_TEXTURE:
9623                         // singletexture unlit texture with transparency support
9624                         R_Mesh_TexBind(0, layer->texture);
9625                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9626                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9627                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9628                         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);
9629                         break;
9630                 case TEXTURELAYERTYPE_FOG:
9631                         // singletexture fogging
9632                         if (layer->texture)
9633                         {
9634                                 R_Mesh_TexBind(0, layer->texture);
9635                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9636                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9637                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9638                         }
9639                         else
9640                         {
9641                                 R_Mesh_TexBind(0, 0);
9642                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9643                         }
9644                         // generate a color array for the fog pass
9645                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9646                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9647                         RSurf_DrawBatch();
9648                         break;
9649                 default:
9650                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9651                 }
9652         }
9653         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9654         {
9655                 GL_DepthFunc(GL_LEQUAL);
9656                 GL_AlphaTest(false);
9657         }
9658 }
9659
9660 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9661 {
9662         int vi;
9663         int j;
9664         r_vertexgeneric_t *batchvertex;
9665         float c[4];
9666
9667 //      R_Mesh_ResetTextureState();
9668         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9669
9670         if(rsurface.texture && rsurface.texture->currentskinframe)
9671         {
9672                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9673                 c[3] *= rsurface.texture->currentalpha;
9674         }
9675         else
9676         {
9677                 c[0] = 1;
9678                 c[1] = 0;
9679                 c[2] = 1;
9680                 c[3] = 1;
9681         }
9682
9683         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9684         {
9685                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9686                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9687                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9688         }
9689
9690         // brighten it up (as texture value 127 means "unlit")
9691         c[0] *= 2 * r_refdef.view.colorscale;
9692         c[1] *= 2 * r_refdef.view.colorscale;
9693         c[2] *= 2 * r_refdef.view.colorscale;
9694
9695         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9696                 c[3] *= r_wateralpha.value;
9697
9698         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9699         {
9700                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9701                 GL_DepthMask(false);
9702         }
9703         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9704         {
9705                 GL_BlendFunc(GL_ONE, GL_ONE);
9706                 GL_DepthMask(false);
9707         }
9708         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9709         {
9710                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9711                 GL_DepthMask(false);
9712         }
9713         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9714         {
9715                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9716                 GL_DepthMask(false);
9717         }
9718         else
9719         {
9720                 GL_BlendFunc(GL_ONE, GL_ZERO);
9721                 GL_DepthMask(writedepth);
9722         }
9723
9724         if (r_showsurfaces.integer == 3)
9725         {
9726                 rsurface.passcolor4f = NULL;
9727
9728                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9729                 {
9730                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9731
9732                         rsurface.passcolor4f = NULL;
9733                         rsurface.passcolor4f_vertexbuffer = 0;
9734                         rsurface.passcolor4f_bufferoffset = 0;
9735                 }
9736                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9737                 {
9738                         qboolean applycolor = true;
9739                         float one = 1.0;
9740
9741                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9742
9743                         r_refdef.lightmapintensity = 1;
9744                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9745                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9746                 }
9747                 else if (FAKELIGHT_ENABLED)
9748                 {
9749                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9750
9751                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9752                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9753                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9754                 }
9755                 else
9756                 {
9757                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9758
9759                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9760                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9761                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9762                 }
9763
9764                 if(!rsurface.passcolor4f)
9765                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9766
9767                 RSurf_DrawBatch_GL11_ApplyAmbient();
9768                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9769                 if(r_refdef.fogenabled)
9770                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9771                 RSurf_DrawBatch_GL11_ClampColor();
9772
9773                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9774                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9775                 RSurf_DrawBatch();
9776         }
9777         else if (!r_refdef.view.showdebug)
9778         {
9779                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9780                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9781                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9782                 {
9783                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9784                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9785                 }
9786                 R_Mesh_PrepareVertices_Generic_Unlock();
9787                 RSurf_DrawBatch();
9788         }
9789         else if (r_showsurfaces.integer == 4)
9790         {
9791                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9792                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9793                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9794                 {
9795                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9796                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9797                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9798                 }
9799                 R_Mesh_PrepareVertices_Generic_Unlock();
9800                 RSurf_DrawBatch();
9801         }
9802         else if (r_showsurfaces.integer == 2)
9803         {
9804                 const int *e;
9805                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9807                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9808                 {
9809                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9810                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9811                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9812                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9813                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9814                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9815                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9816                 }
9817                 R_Mesh_PrepareVertices_Generic_Unlock();
9818                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9819         }
9820         else
9821         {
9822                 int texturesurfaceindex;
9823                 int k;
9824                 const msurface_t *surface;
9825                 float surfacecolor4f[4];
9826                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9827                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9828                 vi = 0;
9829                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9830                 {
9831                         surface = texturesurfacelist[texturesurfaceindex];
9832                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9833                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9834                         for (j = 0;j < surface->num_vertices;j++)
9835                         {
9836                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9837                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9838                                 vi++;
9839                         }
9840                 }
9841                 R_Mesh_PrepareVertices_Generic_Unlock();
9842                 RSurf_DrawBatch();
9843         }
9844 }
9845
9846 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9847 {
9848         CHECKGLERROR
9849         RSurf_SetupDepthAndCulling();
9850         if (r_showsurfaces.integer)
9851         {
9852                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9853                 return;
9854         }
9855         switch (vid.renderpath)
9856         {
9857         case RENDERPATH_GL20:
9858         case RENDERPATH_D3D9:
9859         case RENDERPATH_D3D10:
9860         case RENDERPATH_D3D11:
9861         case RENDERPATH_SOFT:
9862         case RENDERPATH_GLES2:
9863                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9864                 break;
9865         case RENDERPATH_GL13:
9866                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9867                 break;
9868         case RENDERPATH_GL11:
9869                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9870                 break;
9871         }
9872         CHECKGLERROR
9873 }
9874
9875 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9876 {
9877         CHECKGLERROR
9878         RSurf_SetupDepthAndCulling();
9879         if (r_showsurfaces.integer)
9880         {
9881                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9882                 return;
9883         }
9884         switch (vid.renderpath)
9885         {
9886         case RENDERPATH_GL20:
9887         case RENDERPATH_D3D9:
9888         case RENDERPATH_D3D10:
9889         case RENDERPATH_D3D11:
9890         case RENDERPATH_SOFT:
9891         case RENDERPATH_GLES2:
9892                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9893                 break;
9894         case RENDERPATH_GL13:
9895                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9896                 break;
9897         case RENDERPATH_GL11:
9898                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9899                 break;
9900         }
9901         CHECKGLERROR
9902 }
9903
9904 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9905 {
9906         int i, j;
9907         int texturenumsurfaces, endsurface;
9908         texture_t *texture;
9909         const msurface_t *surface;
9910 #define MAXBATCH_TRANSPARENTSURFACES 256
9911         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9912
9913         // if the model is static it doesn't matter what value we give for
9914         // wantnormals and wanttangents, so this logic uses only rules applicable
9915         // to a model, knowing that they are meaningless otherwise
9916         if (ent == r_refdef.scene.worldentity)
9917                 RSurf_ActiveWorldEntity();
9918         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9919                 RSurf_ActiveModelEntity(ent, false, false, false);
9920         else
9921         {
9922                 switch (vid.renderpath)
9923                 {
9924                 case RENDERPATH_GL20:
9925                 case RENDERPATH_D3D9:
9926                 case RENDERPATH_D3D10:
9927                 case RENDERPATH_D3D11:
9928                 case RENDERPATH_SOFT:
9929                 case RENDERPATH_GLES2:
9930                         RSurf_ActiveModelEntity(ent, true, true, false);
9931                         break;
9932                 case RENDERPATH_GL13:
9933                 case RENDERPATH_GL11:
9934                         RSurf_ActiveModelEntity(ent, true, false, false);
9935                         break;
9936                 }
9937         }
9938
9939         if (r_transparentdepthmasking.integer)
9940         {
9941                 qboolean setup = false;
9942                 for (i = 0;i < numsurfaces;i = j)
9943                 {
9944                         j = i + 1;
9945                         surface = rsurface.modelsurfaces + surfacelist[i];
9946                         texture = surface->texture;
9947                         rsurface.texture = R_GetCurrentTexture(texture);
9948                         rsurface.lightmaptexture = NULL;
9949                         rsurface.deluxemaptexture = NULL;
9950                         rsurface.uselightmaptexture = false;
9951                         // scan ahead until we find a different texture
9952                         endsurface = min(i + 1024, numsurfaces);
9953                         texturenumsurfaces = 0;
9954                         texturesurfacelist[texturenumsurfaces++] = surface;
9955                         for (;j < endsurface;j++)
9956                         {
9957                                 surface = rsurface.modelsurfaces + surfacelist[j];
9958                                 if (texture != surface->texture)
9959                                         break;
9960                                 texturesurfacelist[texturenumsurfaces++] = surface;
9961                         }
9962                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9963                                 continue;
9964                         // render the range of surfaces as depth
9965                         if (!setup)
9966                         {
9967                                 setup = true;
9968                                 GL_ColorMask(0,0,0,0);
9969                                 GL_Color(1,1,1,1);
9970                                 GL_DepthTest(true);
9971                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9972                                 GL_DepthMask(true);
9973 //                              R_Mesh_ResetTextureState();
9974                                 R_SetupShader_DepthOrShadow();
9975                         }
9976                         RSurf_SetupDepthAndCulling();
9977                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9978                         if (rsurface.batchvertex3fbuffer)
9979                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9980                         else
9981                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9982                         RSurf_DrawBatch();
9983                 }
9984                 if (setup)
9985                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9986         }
9987
9988         for (i = 0;i < numsurfaces;i = j)
9989         {
9990                 j = i + 1;
9991                 surface = rsurface.modelsurfaces + surfacelist[i];
9992                 texture = surface->texture;
9993                 rsurface.texture = R_GetCurrentTexture(texture);
9994                 // scan ahead until we find a different texture
9995                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9996                 texturenumsurfaces = 0;
9997                 texturesurfacelist[texturenumsurfaces++] = surface;
9998                 if(FAKELIGHT_ENABLED)
9999                 {
10000                         rsurface.lightmaptexture = NULL;
10001                         rsurface.deluxemaptexture = NULL;
10002                         rsurface.uselightmaptexture = false;
10003                         for (;j < endsurface;j++)
10004                         {
10005                                 surface = rsurface.modelsurfaces + surfacelist[j];
10006                                 if (texture != surface->texture)
10007                                         break;
10008                                 texturesurfacelist[texturenumsurfaces++] = surface;
10009                         }
10010                 }
10011                 else
10012                 {
10013                         rsurface.lightmaptexture = surface->lightmaptexture;
10014                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10015                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10016                         for (;j < endsurface;j++)
10017                         {
10018                                 surface = rsurface.modelsurfaces + surfacelist[j];
10019                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10020                                         break;
10021                                 texturesurfacelist[texturenumsurfaces++] = surface;
10022                         }
10023                 }
10024                 // render the range of surfaces
10025                 if (ent == r_refdef.scene.worldentity)
10026                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10027                 else
10028                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10029         }
10030         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10031 }
10032
10033 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10034 {
10035         // transparent surfaces get pushed off into the transparent queue
10036         int surfacelistindex;
10037         const msurface_t *surface;
10038         vec3_t tempcenter, center;
10039         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10040         {
10041                 surface = texturesurfacelist[surfacelistindex];
10042                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10043                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10044                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10045                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10046                 if (queueentity->transparent_offset) // transparent offset
10047                 {
10048                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10049                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10050                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10051                 }
10052                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10053         }
10054 }
10055
10056 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10057 {
10058         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10059                 return;
10060         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10061                 return;
10062         RSurf_SetupDepthAndCulling();
10063         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10064         if (rsurface.batchvertex3fbuffer)
10065                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10066         else
10067                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10068         RSurf_DrawBatch();
10069 }
10070
10071 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10072 {
10073         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10074         CHECKGLERROR
10075         if (depthonly)
10076                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10077         else if (prepass)
10078         {
10079                 if (!rsurface.texture->currentnumlayers)
10080                         return;
10081                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10082                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10083                 else
10084                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10085         }
10086         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10087                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10088         else if (!rsurface.texture->currentnumlayers)
10089                 return;
10090         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10091         {
10092                 // in the deferred case, transparent surfaces were queued during prepass
10093                 if (!r_shadow_usingdeferredprepass)
10094                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10095         }
10096         else
10097         {
10098                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10099                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10100         }
10101         CHECKGLERROR
10102 }
10103
10104 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10105 {
10106         int i, j;
10107         texture_t *texture;
10108         R_FrameData_SetMark();
10109         // break the surface list down into batches by texture and use of lightmapping
10110         for (i = 0;i < numsurfaces;i = j)
10111         {
10112                 j = i + 1;
10113                 // texture is the base texture pointer, rsurface.texture is the
10114                 // current frame/skin the texture is directing us to use (for example
10115                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10116                 // use skin 1 instead)
10117                 texture = surfacelist[i]->texture;
10118                 rsurface.texture = R_GetCurrentTexture(texture);
10119                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10120                 {
10121                         // if this texture is not the kind we want, skip ahead to the next one
10122                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10123                                 ;
10124                         continue;
10125                 }
10126                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10127                 {
10128                         rsurface.lightmaptexture = NULL;
10129                         rsurface.deluxemaptexture = NULL;
10130                         rsurface.uselightmaptexture = false;
10131                         // simply scan ahead until we find a different texture or lightmap state
10132                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10133                                 ;
10134                 }
10135                 else
10136                 {
10137                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10138                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10139                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10140                         // simply scan ahead until we find a different texture or lightmap state
10141                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10142                                 ;
10143                 }
10144                 // render the range of surfaces
10145                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10146         }
10147         R_FrameData_ReturnToMark();
10148 }
10149
10150 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10151 {
10152         CHECKGLERROR
10153         if (depthonly)
10154                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10155         else if (prepass)
10156         {
10157                 if (!rsurface.texture->currentnumlayers)
10158                         return;
10159                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10160                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10161                 else
10162                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10163         }
10164         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10165                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10166         else if (!rsurface.texture->currentnumlayers)
10167                 return;
10168         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10169         {
10170                 // in the deferred case, transparent surfaces were queued during prepass
10171                 if (!r_shadow_usingdeferredprepass)
10172                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10173         }
10174         else
10175         {
10176                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10177                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10178         }
10179         CHECKGLERROR
10180 }
10181
10182 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10183 {
10184         int i, j;
10185         texture_t *texture;
10186         R_FrameData_SetMark();
10187         // break the surface list down into batches by texture and use of lightmapping
10188         for (i = 0;i < numsurfaces;i = j)
10189         {
10190                 j = i + 1;
10191                 // texture is the base texture pointer, rsurface.texture is the
10192                 // current frame/skin the texture is directing us to use (for example
10193                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10194                 // use skin 1 instead)
10195                 texture = surfacelist[i]->texture;
10196                 rsurface.texture = R_GetCurrentTexture(texture);
10197                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10198                 {
10199                         // if this texture is not the kind we want, skip ahead to the next one
10200                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10201                                 ;
10202                         continue;
10203                 }
10204                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10205                 {
10206                         rsurface.lightmaptexture = NULL;
10207                         rsurface.deluxemaptexture = NULL;
10208                         rsurface.uselightmaptexture = false;
10209                         // simply scan ahead until we find a different texture or lightmap state
10210                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10211                                 ;
10212                 }
10213                 else
10214                 {
10215                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10216                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10217                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10218                         // simply scan ahead until we find a different texture or lightmap state
10219                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10220                                 ;
10221                 }
10222                 // render the range of surfaces
10223                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10224         }
10225         R_FrameData_ReturnToMark();
10226 }
10227
10228 float locboxvertex3f[6*4*3] =
10229 {
10230         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10231         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10232         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10233         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10234         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10235         1,0,0, 0,0,0, 0,1,0, 1,1,0
10236 };
10237
10238 unsigned short locboxelements[6*2*3] =
10239 {
10240          0, 1, 2, 0, 2, 3,
10241          4, 5, 6, 4, 6, 7,
10242          8, 9,10, 8,10,11,
10243         12,13,14, 12,14,15,
10244         16,17,18, 16,18,19,
10245         20,21,22, 20,22,23
10246 };
10247
10248 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10249 {
10250         int i, j;
10251         cl_locnode_t *loc = (cl_locnode_t *)ent;
10252         vec3_t mins, size;
10253         float vertex3f[6*4*3];
10254         CHECKGLERROR
10255         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10256         GL_DepthMask(false);
10257         GL_DepthRange(0, 1);
10258         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10259         GL_DepthTest(true);
10260         GL_CullFace(GL_NONE);
10261         R_EntityMatrix(&identitymatrix);
10262
10263 //      R_Mesh_ResetTextureState();
10264
10265         i = surfacelist[0];
10266         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10267                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10268                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10269                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10270
10271         if (VectorCompare(loc->mins, loc->maxs))
10272         {
10273                 VectorSet(size, 2, 2, 2);
10274                 VectorMA(loc->mins, -0.5f, size, mins);
10275         }
10276         else
10277         {
10278                 VectorCopy(loc->mins, mins);
10279                 VectorSubtract(loc->maxs, loc->mins, size);
10280         }
10281
10282         for (i = 0;i < 6*4*3;)
10283                 for (j = 0;j < 3;j++, i++)
10284                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10285
10286         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10287         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10288         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10289 }
10290
10291 void R_DrawLocs(void)
10292 {
10293         int index;
10294         cl_locnode_t *loc, *nearestloc;
10295         vec3_t center;
10296         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10297         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10298         {
10299                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10300                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10301         }
10302 }
10303
10304 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10305 {
10306         if (decalsystem->decals)
10307                 Mem_Free(decalsystem->decals);
10308         memset(decalsystem, 0, sizeof(*decalsystem));
10309 }
10310
10311 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)
10312 {
10313         tridecal_t *decal;
10314         tridecal_t *decals;
10315         int i;
10316
10317         // expand or initialize the system
10318         if (decalsystem->maxdecals <= decalsystem->numdecals)
10319         {
10320                 decalsystem_t old = *decalsystem;
10321                 qboolean useshortelements;
10322                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10323                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10324                 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)));
10325                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10326                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10327                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10328                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10329                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10330                 if (decalsystem->numdecals)
10331                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10332                 if (old.decals)
10333                         Mem_Free(old.decals);
10334                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10335                         decalsystem->element3i[i] = i;
10336                 if (useshortelements)
10337                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10338                                 decalsystem->element3s[i] = i;
10339         }
10340
10341         // grab a decal and search for another free slot for the next one
10342         decals = decalsystem->decals;
10343         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10344         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10345                 ;
10346         decalsystem->freedecal = i;
10347         if (decalsystem->numdecals <= i)
10348                 decalsystem->numdecals = i + 1;
10349
10350         // initialize the decal
10351         decal->lived = 0;
10352         decal->triangleindex = triangleindex;
10353         decal->surfaceindex = surfaceindex;
10354         decal->decalsequence = decalsequence;
10355         decal->color4f[0][0] = c0[0];
10356         decal->color4f[0][1] = c0[1];
10357         decal->color4f[0][2] = c0[2];
10358         decal->color4f[0][3] = 1;
10359         decal->color4f[1][0] = c1[0];
10360         decal->color4f[1][1] = c1[1];
10361         decal->color4f[1][2] = c1[2];
10362         decal->color4f[1][3] = 1;
10363         decal->color4f[2][0] = c2[0];
10364         decal->color4f[2][1] = c2[1];
10365         decal->color4f[2][2] = c2[2];
10366         decal->color4f[2][3] = 1;
10367         decal->vertex3f[0][0] = v0[0];
10368         decal->vertex3f[0][1] = v0[1];
10369         decal->vertex3f[0][2] = v0[2];
10370         decal->vertex3f[1][0] = v1[0];
10371         decal->vertex3f[1][1] = v1[1];
10372         decal->vertex3f[1][2] = v1[2];
10373         decal->vertex3f[2][0] = v2[0];
10374         decal->vertex3f[2][1] = v2[1];
10375         decal->vertex3f[2][2] = v2[2];
10376         decal->texcoord2f[0][0] = t0[0];
10377         decal->texcoord2f[0][1] = t0[1];
10378         decal->texcoord2f[1][0] = t1[0];
10379         decal->texcoord2f[1][1] = t1[1];
10380         decal->texcoord2f[2][0] = t2[0];
10381         decal->texcoord2f[2][1] = t2[1];
10382 }
10383
10384 extern cvar_t cl_decals_bias;
10385 extern cvar_t cl_decals_models;
10386 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10387 // baseparms, parms, temps
10388 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)
10389 {
10390         int cornerindex;
10391         int index;
10392         float v[9][3];
10393         const float *vertex3f;
10394         const float *normal3f;
10395         int numpoints;
10396         float points[2][9][3];
10397         float temp[3];
10398         float tc[9][2];
10399         float f;
10400         float c[9][4];
10401         const int *e;
10402
10403         e = rsurface.modelelement3i + 3*triangleindex;
10404
10405         vertex3f = rsurface.modelvertex3f;
10406         normal3f = rsurface.modelnormal3f;
10407
10408         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10409         {
10410                 index = 3*e[cornerindex];
10411                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10412         }
10413         // cull backfaces
10414         //TriangleNormal(v[0], v[1], v[2], normal);
10415         //if (DotProduct(normal, localnormal) < 0.0f)
10416         //      continue;
10417         // clip by each of the box planes formed from the projection matrix
10418         // if anything survives, we emit the decal
10419         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]);
10420         if (numpoints < 3)
10421                 return;
10422         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]);
10423         if (numpoints < 3)
10424                 return;
10425         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]);
10426         if (numpoints < 3)
10427                 return;
10428         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]);
10429         if (numpoints < 3)
10430                 return;
10431         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]);
10432         if (numpoints < 3)
10433                 return;
10434         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]);
10435         if (numpoints < 3)
10436                 return;
10437         // some part of the triangle survived, so we have to accept it...
10438         if (dynamic)
10439         {
10440                 // dynamic always uses the original triangle
10441                 numpoints = 3;
10442                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10443                 {
10444                         index = 3*e[cornerindex];
10445                         VectorCopy(vertex3f + index, v[cornerindex]);
10446                 }
10447         }
10448         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10449         {
10450                 // convert vertex positions to texcoords
10451                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10452                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10453                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10454                 // calculate distance fade from the projection origin
10455                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10456                 f = bound(0.0f, f, 1.0f);
10457                 c[cornerindex][0] = r * f;
10458                 c[cornerindex][1] = g * f;
10459                 c[cornerindex][2] = b * f;
10460                 c[cornerindex][3] = 1.0f;
10461                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10462         }
10463         if (dynamic)
10464                 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);
10465         else
10466                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10467                         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);
10468 }
10469 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)
10470 {
10471         matrix4x4_t projection;
10472         decalsystem_t *decalsystem;
10473         qboolean dynamic;
10474         dp_model_t *model;
10475         const msurface_t *surface;
10476         const msurface_t *surfaces;
10477         const int *surfacelist;
10478         const texture_t *texture;
10479         int numtriangles;
10480         int numsurfacelist;
10481         int surfacelistindex;
10482         int surfaceindex;
10483         int triangleindex;
10484         float localorigin[3];
10485         float localnormal[3];
10486         float localmins[3];
10487         float localmaxs[3];
10488         float localsize;
10489         //float normal[3];
10490         float planes[6][4];
10491         float angles[3];
10492         bih_t *bih;
10493         int bih_triangles_count;
10494         int bih_triangles[256];
10495         int bih_surfaces[256];
10496
10497         decalsystem = &ent->decalsystem;
10498         model = ent->model;
10499         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10500         {
10501                 R_DecalSystem_Reset(&ent->decalsystem);
10502                 return;
10503         }
10504
10505         if (!model->brush.data_leafs && !cl_decals_models.integer)
10506         {
10507                 if (decalsystem->model)
10508                         R_DecalSystem_Reset(decalsystem);
10509                 return;
10510         }
10511
10512         if (decalsystem->model != model)
10513                 R_DecalSystem_Reset(decalsystem);
10514         decalsystem->model = model;
10515
10516         RSurf_ActiveModelEntity(ent, true, false, false);
10517
10518         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10519         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10520         VectorNormalize(localnormal);
10521         localsize = worldsize*rsurface.inversematrixscale;
10522         localmins[0] = localorigin[0] - localsize;
10523         localmins[1] = localorigin[1] - localsize;
10524         localmins[2] = localorigin[2] - localsize;
10525         localmaxs[0] = localorigin[0] + localsize;
10526         localmaxs[1] = localorigin[1] + localsize;
10527         localmaxs[2] = localorigin[2] + localsize;
10528
10529         //VectorCopy(localnormal, planes[4]);
10530         //VectorVectors(planes[4], planes[2], planes[0]);
10531         AnglesFromVectors(angles, localnormal, NULL, false);
10532         AngleVectors(angles, planes[0], planes[2], planes[4]);
10533         VectorNegate(planes[0], planes[1]);
10534         VectorNegate(planes[2], planes[3]);
10535         VectorNegate(planes[4], planes[5]);
10536         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10537         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10538         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10539         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10540         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10541         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10542
10543 #if 1
10544 // works
10545 {
10546         matrix4x4_t forwardprojection;
10547         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10548         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10549 }
10550 #else
10551 // broken
10552 {
10553         float projectionvector[4][3];
10554         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10555         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10556         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10557         projectionvector[0][0] = planes[0][0] * ilocalsize;
10558         projectionvector[0][1] = planes[1][0] * ilocalsize;
10559         projectionvector[0][2] = planes[2][0] * ilocalsize;
10560         projectionvector[1][0] = planes[0][1] * ilocalsize;
10561         projectionvector[1][1] = planes[1][1] * ilocalsize;
10562         projectionvector[1][2] = planes[2][1] * ilocalsize;
10563         projectionvector[2][0] = planes[0][2] * ilocalsize;
10564         projectionvector[2][1] = planes[1][2] * ilocalsize;
10565         projectionvector[2][2] = planes[2][2] * ilocalsize;
10566         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10567         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10568         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10569         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10570 }
10571 #endif
10572
10573         dynamic = model->surfmesh.isanimated;
10574         numsurfacelist = model->nummodelsurfaces;
10575         surfacelist = model->sortedmodelsurfaces;
10576         surfaces = model->data_surfaces;
10577
10578         bih = NULL;
10579         bih_triangles_count = -1;
10580         if(!dynamic)
10581         {
10582                 if(model->render_bih.numleafs)
10583                         bih = &model->render_bih;
10584                 else if(model->collision_bih.numleafs)
10585                         bih = &model->collision_bih;
10586         }
10587         if(bih)
10588                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10589         if(bih_triangles_count == 0)
10590                 return;
10591         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10592                 return;
10593         if(bih_triangles_count > 0)
10594         {
10595                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10596                 {
10597                         surfaceindex = bih_surfaces[triangleindex];
10598                         surface = surfaces + surfaceindex;
10599                         texture = surface->texture;
10600                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10601                                 continue;
10602                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10603                                 continue;
10604                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10605                 }
10606         }
10607         else
10608         {
10609                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10610                 {
10611                         surfaceindex = surfacelist[surfacelistindex];
10612                         surface = surfaces + surfaceindex;
10613                         // check cull box first because it rejects more than any other check
10614                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10615                                 continue;
10616                         // skip transparent surfaces
10617                         texture = surface->texture;
10618                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10619                                 continue;
10620                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10621                                 continue;
10622                         numtriangles = surface->num_triangles;
10623                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10624                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10625                 }
10626         }
10627 }
10628
10629 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10630 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)
10631 {
10632         int renderentityindex;
10633         float worldmins[3];
10634         float worldmaxs[3];
10635         entity_render_t *ent;
10636
10637         if (!cl_decals_newsystem.integer)
10638                 return;
10639
10640         worldmins[0] = worldorigin[0] - worldsize;
10641         worldmins[1] = worldorigin[1] - worldsize;
10642         worldmins[2] = worldorigin[2] - worldsize;
10643         worldmaxs[0] = worldorigin[0] + worldsize;
10644         worldmaxs[1] = worldorigin[1] + worldsize;
10645         worldmaxs[2] = worldorigin[2] + worldsize;
10646
10647         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10648
10649         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10650         {
10651                 ent = r_refdef.scene.entities[renderentityindex];
10652                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10653                         continue;
10654
10655                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10656         }
10657 }
10658
10659 typedef struct r_decalsystem_splatqueue_s
10660 {
10661         vec3_t worldorigin;
10662         vec3_t worldnormal;
10663         float color[4];
10664         float tcrange[4];
10665         float worldsize;
10666         int decalsequence;
10667 }
10668 r_decalsystem_splatqueue_t;
10669
10670 int r_decalsystem_numqueued = 0;
10671 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10672
10673 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)
10674 {
10675         r_decalsystem_splatqueue_t *queue;
10676
10677         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10678                 return;
10679
10680         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10681         VectorCopy(worldorigin, queue->worldorigin);
10682         VectorCopy(worldnormal, queue->worldnormal);
10683         Vector4Set(queue->color, r, g, b, a);
10684         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10685         queue->worldsize = worldsize;
10686         queue->decalsequence = cl.decalsequence++;
10687 }
10688
10689 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10690 {
10691         int i;
10692         r_decalsystem_splatqueue_t *queue;
10693
10694         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10695                 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);
10696         r_decalsystem_numqueued = 0;
10697 }
10698
10699 extern cvar_t cl_decals_max;
10700 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10701 {
10702         int i;
10703         decalsystem_t *decalsystem = &ent->decalsystem;
10704         int numdecals;
10705         int killsequence;
10706         tridecal_t *decal;
10707         float frametime;
10708         float lifetime;
10709
10710         if (!decalsystem->numdecals)
10711                 return;
10712
10713         if (r_showsurfaces.integer)
10714                 return;
10715
10716         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10717         {
10718                 R_DecalSystem_Reset(decalsystem);
10719                 return;
10720         }
10721
10722         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10723         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10724
10725         if (decalsystem->lastupdatetime)
10726                 frametime = (cl.time - decalsystem->lastupdatetime);
10727         else
10728                 frametime = 0;
10729         decalsystem->lastupdatetime = cl.time;
10730         decal = decalsystem->decals;
10731         numdecals = decalsystem->numdecals;
10732
10733         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10734         {
10735                 if (decal->color4f[0][3])
10736                 {
10737                         decal->lived += frametime;
10738                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10739                         {
10740                                 memset(decal, 0, sizeof(*decal));
10741                                 if (decalsystem->freedecal > i)
10742                                         decalsystem->freedecal = i;
10743                         }
10744                 }
10745         }
10746         decal = decalsystem->decals;
10747         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10748                 numdecals--;
10749
10750         // collapse the array by shuffling the tail decals into the gaps
10751         for (;;)
10752         {
10753                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10754                         decalsystem->freedecal++;
10755                 if (decalsystem->freedecal == numdecals)
10756                         break;
10757                 decal[decalsystem->freedecal] = decal[--numdecals];
10758         }
10759
10760         decalsystem->numdecals = numdecals;
10761
10762         if (numdecals <= 0)
10763         {
10764                 // if there are no decals left, reset decalsystem
10765                 R_DecalSystem_Reset(decalsystem);
10766         }
10767 }
10768
10769 extern skinframe_t *decalskinframe;
10770 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10771 {
10772         int i;
10773         decalsystem_t *decalsystem = &ent->decalsystem;
10774         int numdecals;
10775         tridecal_t *decal;
10776         float faderate;
10777         float alpha;
10778         float *v3f;
10779         float *c4f;
10780         float *t2f;
10781         const int *e;
10782         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10783         int numtris = 0;
10784
10785         numdecals = decalsystem->numdecals;
10786         if (!numdecals)
10787                 return;
10788
10789         if (r_showsurfaces.integer)
10790                 return;
10791
10792         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10793         {
10794                 R_DecalSystem_Reset(decalsystem);
10795                 return;
10796         }
10797
10798         // if the model is static it doesn't matter what value we give for
10799         // wantnormals and wanttangents, so this logic uses only rules applicable
10800         // to a model, knowing that they are meaningless otherwise
10801         if (ent == r_refdef.scene.worldentity)
10802                 RSurf_ActiveWorldEntity();
10803         else
10804                 RSurf_ActiveModelEntity(ent, false, false, false);
10805
10806         decalsystem->lastupdatetime = cl.time;
10807         decal = decalsystem->decals;
10808
10809         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10810
10811         // update vertex positions for animated models
10812         v3f = decalsystem->vertex3f;
10813         c4f = decalsystem->color4f;
10814         t2f = decalsystem->texcoord2f;
10815         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10816         {
10817                 if (!decal->color4f[0][3])
10818                         continue;
10819
10820                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10821                         continue;
10822
10823                 // update color values for fading decals
10824                 if (decal->lived >= cl_decals_time.value)
10825                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10826                 else
10827                         alpha = 1.0f;
10828
10829                 c4f[ 0] = decal->color4f[0][0] * alpha;
10830                 c4f[ 1] = decal->color4f[0][1] * alpha;
10831                 c4f[ 2] = decal->color4f[0][2] * alpha;
10832                 c4f[ 3] = 1;
10833                 c4f[ 4] = decal->color4f[1][0] * alpha;
10834                 c4f[ 5] = decal->color4f[1][1] * alpha;
10835                 c4f[ 6] = decal->color4f[1][2] * alpha;
10836                 c4f[ 7] = 1;
10837                 c4f[ 8] = decal->color4f[2][0] * alpha;
10838                 c4f[ 9] = decal->color4f[2][1] * alpha;
10839                 c4f[10] = decal->color4f[2][2] * alpha;
10840                 c4f[11] = 1;
10841
10842                 t2f[0] = decal->texcoord2f[0][0];
10843                 t2f[1] = decal->texcoord2f[0][1];
10844                 t2f[2] = decal->texcoord2f[1][0];
10845                 t2f[3] = decal->texcoord2f[1][1];
10846                 t2f[4] = decal->texcoord2f[2][0];
10847                 t2f[5] = decal->texcoord2f[2][1];
10848
10849                 // update vertex positions for animated models
10850                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10851                 {
10852                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10853                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10854                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10855                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10856                 }
10857                 else
10858                 {
10859                         VectorCopy(decal->vertex3f[0], v3f);
10860                         VectorCopy(decal->vertex3f[1], v3f + 3);
10861                         VectorCopy(decal->vertex3f[2], v3f + 6);
10862                 }
10863
10864                 if (r_refdef.fogenabled)
10865                 {
10866                         alpha = RSurf_FogVertex(v3f);
10867                         VectorScale(c4f, alpha, c4f);
10868                         alpha = RSurf_FogVertex(v3f + 3);
10869                         VectorScale(c4f + 4, alpha, c4f + 4);
10870                         alpha = RSurf_FogVertex(v3f + 6);
10871                         VectorScale(c4f + 8, alpha, c4f + 8);
10872                 }
10873
10874                 v3f += 9;
10875                 c4f += 12;
10876                 t2f += 6;
10877                 numtris++;
10878         }
10879
10880         if (numtris > 0)
10881         {
10882                 r_refdef.stats.drawndecals += numtris;
10883
10884                 // now render the decals all at once
10885                 // (this assumes they all use one particle font texture!)
10886                 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);
10887 //              R_Mesh_ResetTextureState();
10888                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10889                 GL_DepthMask(false);
10890                 GL_DepthRange(0, 1);
10891                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10892                 GL_DepthTest(true);
10893                 GL_CullFace(GL_NONE);
10894                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10895                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10896                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10897         }
10898 }
10899
10900 static void R_DrawModelDecals(void)
10901 {
10902         int i, numdecals;
10903
10904         // fade faster when there are too many decals
10905         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10906         for (i = 0;i < r_refdef.scene.numentities;i++)
10907                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10908
10909         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10910         for (i = 0;i < r_refdef.scene.numentities;i++)
10911                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10912                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10913
10914         R_DecalSystem_ApplySplatEntitiesQueue();
10915
10916         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10917         for (i = 0;i < r_refdef.scene.numentities;i++)
10918                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10919
10920         r_refdef.stats.totaldecals += numdecals;
10921
10922         if (r_showsurfaces.integer)
10923                 return;
10924
10925         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10926
10927         for (i = 0;i < r_refdef.scene.numentities;i++)
10928         {
10929                 if (!r_refdef.viewcache.entityvisible[i])
10930                         continue;
10931                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10932                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10933         }
10934 }
10935
10936 extern cvar_t mod_collision_bih;
10937 void R_DrawDebugModel(void)
10938 {
10939         entity_render_t *ent = rsurface.entity;
10940         int i, j, k, l, flagsmask;
10941         const msurface_t *surface;
10942         dp_model_t *model = ent->model;
10943         vec3_t v;
10944
10945         switch(vid.renderpath)
10946         {
10947         case RENDERPATH_GL11:
10948         case RENDERPATH_GL13:
10949         case RENDERPATH_GL20:
10950                 break;
10951         case RENDERPATH_D3D9:
10952                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10953                 return;
10954         case RENDERPATH_D3D10:
10955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10956                 return;
10957         case RENDERPATH_D3D11:
10958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10959                 return;
10960         case RENDERPATH_SOFT:
10961                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10962                 return;
10963         case RENDERPATH_GLES2:
10964                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10965                 return;
10966         }
10967
10968         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10969
10970 //      R_Mesh_ResetTextureState();
10971         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10972         GL_DepthRange(0, 1);
10973         GL_DepthTest(!r_showdisabledepthtest.integer);
10974         GL_DepthMask(false);
10975         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10976
10977         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10978         {
10979                 int triangleindex;
10980                 int bihleafindex;
10981                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10982                 const q3mbrush_t *brush;
10983                 const bih_t *bih = &model->collision_bih;
10984                 const bih_leaf_t *bihleaf;
10985                 float vertex3f[3][3];
10986                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10987                 cullbox = false;
10988                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10989                 {
10990                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10991                                 continue;
10992                         switch (bihleaf->type)
10993                         {
10994                         case BIH_BRUSH:
10995                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10996                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10997                                 {
10998                                         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);
10999                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11000                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11001                                 }
11002                                 break;
11003                         case BIH_COLLISIONTRIANGLE:
11004                                 triangleindex = bihleaf->itemindex;
11005                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11006                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11007                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11008                                 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);
11009                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11010                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11011                                 break;
11012                         case BIH_RENDERTRIANGLE:
11013                                 triangleindex = bihleaf->itemindex;
11014                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11015                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11016                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11017                                 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);
11018                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11019                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11020                                 break;
11021                         }
11022                 }
11023         }
11024
11025         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11026
11027         if (r_showtris.integer || (r_shownormals.value != 0))
11028         {
11029                 if (r_showdisabledepthtest.integer)
11030                 {
11031                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11032                         GL_DepthMask(false);
11033                 }
11034                 else
11035                 {
11036                         GL_BlendFunc(GL_ONE, GL_ZERO);
11037                         GL_DepthMask(true);
11038                 }
11039                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11040                 {
11041                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11042                                 continue;
11043                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11044                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11045                         {
11046                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11047                                 if (r_showtris.value > 0)
11048                                 {
11049                                         if (!rsurface.texture->currentlayers->depthmask)
11050                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11051                                         else if (ent == r_refdef.scene.worldentity)
11052                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11053                                         else
11054                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11055                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11056                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11057                                         RSurf_DrawBatch();
11058                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11059                                         CHECKGLERROR
11060                                 }
11061                                 if (r_shownormals.value < 0)
11062                                 {
11063                                         qglBegin(GL_LINES);
11064                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11065                                         {
11066                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11067                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11068                                                 qglVertex3f(v[0], v[1], v[2]);
11069                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11070                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11071                                                 qglVertex3f(v[0], v[1], v[2]);
11072                                         }
11073                                         qglEnd();
11074                                         CHECKGLERROR
11075                                 }
11076                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11077                                 {
11078                                         qglBegin(GL_LINES);
11079                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11080                                         {
11081                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11082                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11083                                                 qglVertex3f(v[0], v[1], v[2]);
11084                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11085                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11086                                                 qglVertex3f(v[0], v[1], v[2]);
11087                                         }
11088                                         qglEnd();
11089                                         CHECKGLERROR
11090                                         qglBegin(GL_LINES);
11091                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11092                                         {
11093                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11094                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11095                                                 qglVertex3f(v[0], v[1], v[2]);
11096                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11097                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11098                                                 qglVertex3f(v[0], v[1], v[2]);
11099                                         }
11100                                         qglEnd();
11101                                         CHECKGLERROR
11102                                         qglBegin(GL_LINES);
11103                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11104                                         {
11105                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11106                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11107                                                 qglVertex3f(v[0], v[1], v[2]);
11108                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11109                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11110                                                 qglVertex3f(v[0], v[1], v[2]);
11111                                         }
11112                                         qglEnd();
11113                                         CHECKGLERROR
11114                                 }
11115                         }
11116                 }
11117                 rsurface.texture = NULL;
11118         }
11119 }
11120
11121 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11122 int r_maxsurfacelist = 0;
11123 const msurface_t **r_surfacelist = NULL;
11124 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11125 {
11126         int i, j, endj, flagsmask;
11127         dp_model_t *model = r_refdef.scene.worldmodel;
11128         msurface_t *surfaces;
11129         unsigned char *update;
11130         int numsurfacelist = 0;
11131         if (model == NULL)
11132                 return;
11133
11134         if (r_maxsurfacelist < model->num_surfaces)
11135         {
11136                 r_maxsurfacelist = model->num_surfaces;
11137                 if (r_surfacelist)
11138                         Mem_Free((msurface_t**)r_surfacelist);
11139                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11140         }
11141
11142         RSurf_ActiveWorldEntity();
11143
11144         surfaces = model->data_surfaces;
11145         update = model->brushq1.lightmapupdateflags;
11146
11147         // update light styles on this submodel
11148         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11149         {
11150                 model_brush_lightstyleinfo_t *style;
11151                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11152                 {
11153                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11154                         {
11155                                 int *list = style->surfacelist;
11156                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11157                                 for (j = 0;j < style->numsurfaces;j++)
11158                                         update[list[j]] = true;
11159                         }
11160                 }
11161         }
11162
11163         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11164
11165         if (debug)
11166         {
11167                 R_DrawDebugModel();
11168                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11169                 return;
11170         }
11171
11172         rsurface.lightmaptexture = NULL;
11173         rsurface.deluxemaptexture = NULL;
11174         rsurface.uselightmaptexture = false;
11175         rsurface.texture = NULL;
11176         rsurface.rtlight = NULL;
11177         numsurfacelist = 0;
11178         // add visible surfaces to draw list
11179         for (i = 0;i < model->nummodelsurfaces;i++)
11180         {
11181                 j = model->sortedmodelsurfaces[i];
11182                 if (r_refdef.viewcache.world_surfacevisible[j])
11183                         r_surfacelist[numsurfacelist++] = surfaces + j;
11184         }
11185         // update lightmaps if needed
11186         if (model->brushq1.firstrender)
11187         {
11188                 model->brushq1.firstrender = false;
11189                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11190                         if (update[j])
11191                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11192         }
11193         else if (update)
11194         {
11195                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11196                         if (r_refdef.viewcache.world_surfacevisible[j])
11197                                 if (update[j])
11198                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11199         }
11200         // don't do anything if there were no surfaces
11201         if (!numsurfacelist)
11202         {
11203                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11204                 return;
11205         }
11206         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11207
11208         // add to stats if desired
11209         if (r_speeds.integer && !skysurfaces && !depthonly)
11210         {
11211                 r_refdef.stats.world_surfaces += numsurfacelist;
11212                 for (j = 0;j < numsurfacelist;j++)
11213                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11214         }
11215
11216         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11217 }
11218
11219 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11220 {
11221         int i, j, endj, flagsmask;
11222         dp_model_t *model = ent->model;
11223         msurface_t *surfaces;
11224         unsigned char *update;
11225         int numsurfacelist = 0;
11226         if (model == NULL)
11227                 return;
11228
11229         if (r_maxsurfacelist < model->num_surfaces)
11230         {
11231                 r_maxsurfacelist = model->num_surfaces;
11232                 if (r_surfacelist)
11233                         Mem_Free((msurface_t **)r_surfacelist);
11234                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11235         }
11236
11237         // if the model is static it doesn't matter what value we give for
11238         // wantnormals and wanttangents, so this logic uses only rules applicable
11239         // to a model, knowing that they are meaningless otherwise
11240         if (ent == r_refdef.scene.worldentity)
11241                 RSurf_ActiveWorldEntity();
11242         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11243                 RSurf_ActiveModelEntity(ent, false, false, false);
11244         else if (prepass)
11245                 RSurf_ActiveModelEntity(ent, true, true, true);
11246         else if (depthonly)
11247         {
11248                 switch (vid.renderpath)
11249                 {
11250                 case RENDERPATH_GL20:
11251                 case RENDERPATH_D3D9:
11252                 case RENDERPATH_D3D10:
11253                 case RENDERPATH_D3D11:
11254                 case RENDERPATH_SOFT:
11255                 case RENDERPATH_GLES2:
11256                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11257                         break;
11258                 case RENDERPATH_GL13:
11259                 case RENDERPATH_GL11:
11260                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11261                         break;
11262                 }
11263         }
11264         else
11265         {
11266                 switch (vid.renderpath)
11267                 {
11268                 case RENDERPATH_GL20:
11269                 case RENDERPATH_D3D9:
11270                 case RENDERPATH_D3D10:
11271                 case RENDERPATH_D3D11:
11272                 case RENDERPATH_SOFT:
11273                 case RENDERPATH_GLES2:
11274                         RSurf_ActiveModelEntity(ent, true, true, false);
11275                         break;
11276                 case RENDERPATH_GL13:
11277                 case RENDERPATH_GL11:
11278                         RSurf_ActiveModelEntity(ent, true, false, false);
11279                         break;
11280                 }
11281         }
11282
11283         surfaces = model->data_surfaces;
11284         update = model->brushq1.lightmapupdateflags;
11285
11286         // update light styles
11287         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11288         {
11289                 model_brush_lightstyleinfo_t *style;
11290                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11291                 {
11292                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11293                         {
11294                                 int *list = style->surfacelist;
11295                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11296                                 for (j = 0;j < style->numsurfaces;j++)
11297                                         update[list[j]] = true;
11298                         }
11299                 }
11300         }
11301
11302         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11303
11304         if (debug)
11305         {
11306                 R_DrawDebugModel();
11307                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11308                 return;
11309         }
11310
11311         rsurface.lightmaptexture = NULL;
11312         rsurface.deluxemaptexture = NULL;
11313         rsurface.uselightmaptexture = false;
11314         rsurface.texture = NULL;
11315         rsurface.rtlight = NULL;
11316         numsurfacelist = 0;
11317         // add visible surfaces to draw list
11318         for (i = 0;i < model->nummodelsurfaces;i++)
11319                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11320         // don't do anything if there were no surfaces
11321         if (!numsurfacelist)
11322         {
11323                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11324                 return;
11325         }
11326         // update lightmaps if needed
11327         if (update)
11328         {
11329                 int updated = 0;
11330                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11331                 {
11332                         if (update[j])
11333                         {
11334                                 updated++;
11335                                 R_BuildLightMap(ent, surfaces + j);
11336                         }
11337                 }
11338         }
11339         if (update)
11340                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11341                         if (update[j])
11342                                 R_BuildLightMap(ent, surfaces + j);
11343         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11344
11345         // add to stats if desired
11346         if (r_speeds.integer && !skysurfaces && !depthonly)
11347         {
11348                 r_refdef.stats.entities_surfaces += numsurfacelist;
11349                 for (j = 0;j < numsurfacelist;j++)
11350                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11351         }
11352
11353         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11354 }
11355
11356 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11357 {
11358         static texture_t texture;
11359         static msurface_t surface;
11360         const msurface_t *surfacelist = &surface;
11361
11362         // fake enough texture and surface state to render this geometry
11363
11364         texture.update_lastrenderframe = -1; // regenerate this texture
11365         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11366         texture.currentskinframe = skinframe;
11367         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11368         texture.offsetmapping = OFFSETMAPPING_OFF;
11369         texture.offsetscale = 1;
11370         texture.specularscalemod = 1;
11371         texture.specularpowermod = 1;
11372
11373         surface.texture = &texture;
11374         surface.num_triangles = numtriangles;
11375         surface.num_firsttriangle = firsttriangle;
11376         surface.num_vertices = numvertices;
11377         surface.num_firstvertex = firstvertex;
11378
11379         // now render it
11380         rsurface.texture = R_GetCurrentTexture(surface.texture);
11381         rsurface.lightmaptexture = NULL;
11382         rsurface.deluxemaptexture = NULL;
11383         rsurface.uselightmaptexture = false;
11384         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11385 }
11386
11387 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)
11388 {
11389         static msurface_t surface;
11390         const msurface_t *surfacelist = &surface;
11391
11392         // fake enough texture and surface state to render this geometry
11393         surface.texture = texture;
11394         surface.num_triangles = numtriangles;
11395         surface.num_firsttriangle = firsttriangle;
11396         surface.num_vertices = numvertices;
11397         surface.num_firstvertex = firstvertex;
11398
11399         // now render it
11400         rsurface.texture = R_GetCurrentTexture(surface.texture);
11401         rsurface.lightmaptexture = NULL;
11402         rsurface.deluxemaptexture = NULL;
11403         rsurface.uselightmaptexture = false;
11404         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11405 }