]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
add a hack to support fog on premultiplied alpha surfaces too
[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 USEFOGALPHAHACK\n", " fogalphahack"},
637         {"#define USEGAMMARAMPS\n", " gammaramps"},
638         {"#define USECUBEFILTER\n", " cubefilter"},
639         {"#define USEGLOW\n", " glow"},
640         {"#define USEBLOOM\n", " bloom"},
641         {"#define USESPECULAR\n", " specular"},
642         {"#define USEPOSTPROCESSING\n", " postprocessing"},
643         {"#define USEREFLECTION\n", " reflection"},
644         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
645         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
646         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
647         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
648         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
649         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
650         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
651         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653         {"#define USEALPHAKILL\n", " alphakill"},
654         {"#define USEREFLECTCUBE\n", " reflectcube"},
655         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656         {"#define USEBOUNCEGRID\n", " bouncegrid"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
678 };
679
680 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
681 {
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
698 };
699
700 struct r_glsl_permutation_s;
701 typedef struct r_glsl_permutation_s
702 {
703         /// hash lookup data
704         struct r_glsl_permutation_s *hashnext;
705         unsigned int mode;
706         unsigned int permutation;
707
708         /// indicates if we have tried compiling this permutation already
709         qboolean compiled;
710         /// 0 if compilation failed
711         int program;
712         // texture units assigned to each detected uniform
713         int tex_Texture_First;
714         int tex_Texture_Second;
715         int tex_Texture_GammaRamps;
716         int tex_Texture_Normal;
717         int tex_Texture_Color;
718         int tex_Texture_Gloss;
719         int tex_Texture_Glow;
720         int tex_Texture_SecondaryNormal;
721         int tex_Texture_SecondaryColor;
722         int tex_Texture_SecondaryGloss;
723         int tex_Texture_SecondaryGlow;
724         int tex_Texture_Pants;
725         int tex_Texture_Shirt;
726         int tex_Texture_FogHeightTexture;
727         int tex_Texture_FogMask;
728         int tex_Texture_Lightmap;
729         int tex_Texture_Deluxemap;
730         int tex_Texture_Attenuation;
731         int tex_Texture_Cube;
732         int tex_Texture_Refraction;
733         int tex_Texture_Reflection;
734         int tex_Texture_ShadowMap2D;
735         int tex_Texture_CubeProjection;
736         int tex_Texture_ScreenDepth;
737         int tex_Texture_ScreenNormalMap;
738         int tex_Texture_ScreenDiffuse;
739         int tex_Texture_ScreenSpecular;
740         int tex_Texture_ReflectMask;
741         int tex_Texture_ReflectCube;
742         int tex_Texture_BounceGrid;
743         /// locations of detected uniforms in program object, or -1 if not found
744         int loc_Texture_First;
745         int loc_Texture_Second;
746         int loc_Texture_GammaRamps;
747         int loc_Texture_Normal;
748         int loc_Texture_Color;
749         int loc_Texture_Gloss;
750         int loc_Texture_Glow;
751         int loc_Texture_SecondaryNormal;
752         int loc_Texture_SecondaryColor;
753         int loc_Texture_SecondaryGloss;
754         int loc_Texture_SecondaryGlow;
755         int loc_Texture_Pants;
756         int loc_Texture_Shirt;
757         int loc_Texture_FogHeightTexture;
758         int loc_Texture_FogMask;
759         int loc_Texture_Lightmap;
760         int loc_Texture_Deluxemap;
761         int loc_Texture_Attenuation;
762         int loc_Texture_Cube;
763         int loc_Texture_Refraction;
764         int loc_Texture_Reflection;
765         int loc_Texture_ShadowMap2D;
766         int loc_Texture_CubeProjection;
767         int loc_Texture_ScreenDepth;
768         int loc_Texture_ScreenNormalMap;
769         int loc_Texture_ScreenDiffuse;
770         int loc_Texture_ScreenSpecular;
771         int loc_Texture_ReflectMask;
772         int loc_Texture_ReflectCube;
773         int loc_Texture_BounceGrid;
774         int loc_Alpha;
775         int loc_BloomBlur_Parameters;
776         int loc_ClientTime;
777         int loc_Color_Ambient;
778         int loc_Color_Diffuse;
779         int loc_Color_Specular;
780         int loc_Color_Glow;
781         int loc_Color_Pants;
782         int loc_Color_Shirt;
783         int loc_DeferredColor_Ambient;
784         int loc_DeferredColor_Diffuse;
785         int loc_DeferredColor_Specular;
786         int loc_DeferredMod_Diffuse;
787         int loc_DeferredMod_Specular;
788         int loc_DistortScaleRefractReflect;
789         int loc_EyePosition;
790         int loc_FogColor;
791         int loc_FogHeightFade;
792         int loc_FogPlane;
793         int loc_FogPlaneViewDist;
794         int loc_FogRangeRecip;
795         int loc_LightColor;
796         int loc_LightDir;
797         int loc_LightPosition;
798         int loc_OffsetMapping_Scale;
799         int loc_PixelSize;
800         int loc_ReflectColor;
801         int loc_ReflectFactor;
802         int loc_ReflectOffset;
803         int loc_RefractColor;
804         int loc_Saturation;
805         int loc_ScreenCenterRefractReflect;
806         int loc_ScreenScaleRefractReflect;
807         int loc_ScreenToDepth;
808         int loc_ShadowMap_Parameters;
809         int loc_ShadowMap_TextureScale;
810         int loc_SpecularPower;
811         int loc_UserVec1;
812         int loc_UserVec2;
813         int loc_UserVec3;
814         int loc_UserVec4;
815         int loc_ViewTintColor;
816         int loc_ViewToLight;
817         int loc_ModelToLight;
818         int loc_TexMatrix;
819         int loc_BackgroundTexMatrix;
820         int loc_ModelViewProjectionMatrix;
821         int loc_ModelViewMatrix;
822         int loc_PixelToScreenTexCoord;
823         int loc_ModelToReflectCube;
824         int loc_ShadowMapMatrix;
825         int loc_BloomColorSubtract;
826         int loc_NormalmapScrollBlend;
827         int loc_BounceGridMatrix;
828         int loc_BounceGridIntensity;
829 }
830 r_glsl_permutation_t;
831
832 #define SHADERPERMUTATION_HASHSIZE 256
833
834
835 // non-degradable "lightweight" shader parameters to keep the permutations simpler
836 // these can NOT degrade! only use for simple stuff
837 enum
838 {
839         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
840         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
841         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
842         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
843         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
844         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
845 };
846 #define SHADERSTATICPARMS_COUNT 6
847
848 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
849 static int shaderstaticparms_count = 0;
850
851 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
852 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
853 qboolean R_CompileShader_CheckStaticParms(void)
854 {
855         static int r_compileshader_staticparms_save[1];
856         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
857         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
858
859         // detect all
860         if (r_glsl_saturation_redcompensate.integer)
861                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
862         if (r_shadow_glossexact.integer)
863                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
864         if (r_glsl_postprocess.integer)
865         {
866                 if (r_glsl_postprocess_uservec1_enable.integer)
867                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
868                 if (r_glsl_postprocess_uservec2_enable.integer)
869                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
870                 if (r_glsl_postprocess_uservec3_enable.integer)
871                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
872                 if (r_glsl_postprocess_uservec4_enable.integer)
873                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
874         }
875         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
876 }
877
878 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
879         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
880                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
881         else \
882                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
883 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
884 {
885         shaderstaticparms_count = 0;
886
887         // emit all
888         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
889         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
894 }
895
896 /// information about each possible shader permutation
897 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
898 /// currently selected permutation
899 r_glsl_permutation_t *r_glsl_permutation;
900 /// storage for permutations linked in the hash table
901 memexpandablearray_t r_glsl_permutationarray;
902
903 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
904 {
905         //unsigned int hashdepth = 0;
906         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
907         r_glsl_permutation_t *p;
908         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
909         {
910                 if (p->mode == mode && p->permutation == permutation)
911                 {
912                         //if (hashdepth > 10)
913                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
914                         return p;
915                 }
916                 //hashdepth++;
917         }
918         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
919         p->mode = mode;
920         p->permutation = permutation;
921         p->hashnext = r_glsl_permutationhash[mode][hashindex];
922         r_glsl_permutationhash[mode][hashindex] = p;
923         //if (hashdepth > 10)
924         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
925         return p;
926 }
927
928 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
929 {
930         char *shaderstring;
931         if (!filename || !filename[0])
932                 return NULL;
933         if (!strcmp(filename, "glsl/default.glsl"))
934         {
935                 if (!glslshaderstring)
936                 {
937                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
938                         if (glslshaderstring)
939                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
940                         else
941                                 glslshaderstring = (char *)builtinshaderstring;
942                 }
943                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
944                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
945                 return shaderstring;
946         }
947         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948         if (shaderstring)
949         {
950                 if (printfromdisknotice)
951                         Con_DPrintf("from disk %s... ", filename);
952                 return shaderstring;
953         }
954         return shaderstring;
955 }
956
957 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
958 {
959         int i;
960         int sampler;
961         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
962         char *vertexstring, *geometrystring, *fragmentstring;
963         char permutationname[256];
964         int vertstrings_count = 0;
965         int geomstrings_count = 0;
966         int fragstrings_count = 0;
967         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
970
971         if (p->compiled)
972                 return;
973         p->compiled = true;
974         p->program = 0;
975
976         permutationname[0] = 0;
977         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
978         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
979         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
980
981         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
982
983         // the first pretext is which type of shader to compile as
984         // (later these will all be bound together as a program object)
985         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
986         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
987         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
988
989         // the second pretext is the mode (for example a light source)
990         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
991         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
992         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
993         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
994
995         // now add all the permutation pretexts
996         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
997         {
998                 if (permutation & (1<<i))
999                 {
1000                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1001                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1002                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1003                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1004                 }
1005                 else
1006                 {
1007                         // keep line numbers correct
1008                         vertstrings_list[vertstrings_count++] = "\n";
1009                         geomstrings_list[geomstrings_count++] = "\n";
1010                         fragstrings_list[fragstrings_count++] = "\n";
1011                 }
1012         }
1013
1014         // add static parms
1015         R_CompileShader_AddStaticParms(mode, permutation);
1016         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1017         vertstrings_count += shaderstaticparms_count;
1018         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1019         geomstrings_count += shaderstaticparms_count;
1020         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1021         fragstrings_count += shaderstaticparms_count;
1022
1023         // now append the shader text itself
1024         vertstrings_list[vertstrings_count++] = vertexstring;
1025         geomstrings_list[geomstrings_count++] = geometrystring;
1026         fragstrings_list[fragstrings_count++] = fragmentstring;
1027
1028         // if any sources were NULL, clear the respective list
1029         if (!vertexstring)
1030                 vertstrings_count = 0;
1031         if (!geometrystring)
1032                 geomstrings_count = 0;
1033         if (!fragmentstring)
1034                 fragstrings_count = 0;
1035
1036         // compile the shader program
1037         if (vertstrings_count + geomstrings_count + fragstrings_count)
1038                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1039         if (p->program)
1040         {
1041                 CHECKGLERROR
1042                 qglUseProgram(p->program);CHECKGLERROR
1043                 // look up all the uniform variable names we care about, so we don't
1044                 // have to look them up every time we set them
1045
1046                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1047                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1048                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1049                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1050                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1051                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1052                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1053                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1054                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1055                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1056                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1057                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1058                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1059                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1060                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1061                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1062                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1063                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1064                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1065                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1066                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1067                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1068                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1069                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1070                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1071                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1072                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1073                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1074                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1075                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1076                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1077                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1078                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1079                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1080                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1081                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1082                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1083                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1084                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1085                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1086                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1087                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1088                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1089                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1090                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1091                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1092                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1093                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1094                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1095                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1096                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1097                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1098                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1099                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1100                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1101                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1102                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1103                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1104                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1105                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1106                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1107                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1108                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1109                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1110                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1111                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1112                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1113                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1114                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1115                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1116                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1117                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1118                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1119                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1120                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1121                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1122                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1123                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1124                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1125                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1126                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1127                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1128                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1129                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1130                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1131                 // initialize the samplers to refer to the texture units we use
1132                 p->tex_Texture_First = -1;
1133                 p->tex_Texture_Second = -1;
1134                 p->tex_Texture_GammaRamps = -1;
1135                 p->tex_Texture_Normal = -1;
1136                 p->tex_Texture_Color = -1;
1137                 p->tex_Texture_Gloss = -1;
1138                 p->tex_Texture_Glow = -1;
1139                 p->tex_Texture_SecondaryNormal = -1;
1140                 p->tex_Texture_SecondaryColor = -1;
1141                 p->tex_Texture_SecondaryGloss = -1;
1142                 p->tex_Texture_SecondaryGlow = -1;
1143                 p->tex_Texture_Pants = -1;
1144                 p->tex_Texture_Shirt = -1;
1145                 p->tex_Texture_FogHeightTexture = -1;
1146                 p->tex_Texture_FogMask = -1;
1147                 p->tex_Texture_Lightmap = -1;
1148                 p->tex_Texture_Deluxemap = -1;
1149                 p->tex_Texture_Attenuation = -1;
1150                 p->tex_Texture_Cube = -1;
1151                 p->tex_Texture_Refraction = -1;
1152                 p->tex_Texture_Reflection = -1;
1153                 p->tex_Texture_ShadowMap2D = -1;
1154                 p->tex_Texture_CubeProjection = -1;
1155                 p->tex_Texture_ScreenDepth = -1;
1156                 p->tex_Texture_ScreenNormalMap = -1;
1157                 p->tex_Texture_ScreenDiffuse = -1;
1158                 p->tex_Texture_ScreenSpecular = -1;
1159                 p->tex_Texture_ReflectMask = -1;
1160                 p->tex_Texture_ReflectCube = -1;
1161                 p->tex_Texture_BounceGrid = -1;
1162                 sampler = 0;
1163                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1164                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1165                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1166                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1167                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1168                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1169                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1170                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1171                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1172                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1173                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1174                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1175                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1176                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1177                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1178                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1179                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1180                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1181                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1182                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1183                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1184                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1185                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1186                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1187                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1188                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1189                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1190                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1191                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1192                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1193                 CHECKGLERROR
1194                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1195         }
1196         else
1197                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1198
1199         // free the strings
1200         if (vertexstring)
1201                 Mem_Free(vertexstring);
1202         if (geometrystring)
1203                 Mem_Free(geometrystring);
1204         if (fragmentstring)
1205                 Mem_Free(fragmentstring);
1206 }
1207
1208 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1209 {
1210         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1211         if (r_glsl_permutation != perm)
1212         {
1213                 r_glsl_permutation = perm;
1214                 if (!r_glsl_permutation->program)
1215                 {
1216                         if (!r_glsl_permutation->compiled)
1217                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1218                         if (!r_glsl_permutation->program)
1219                         {
1220                                 // remove features until we find a valid permutation
1221                                 int i;
1222                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1223                                 {
1224                                         // reduce i more quickly whenever it would not remove any bits
1225                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1226                                         if (!(permutation & j))
1227                                                 continue;
1228                                         permutation -= j;
1229                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1230                                         if (!r_glsl_permutation->compiled)
1231                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1232                                         if (r_glsl_permutation->program)
1233                                                 break;
1234                                 }
1235                                 if (i >= SHADERPERMUTATION_COUNT)
1236                                 {
1237                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1238                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1239                                         qglUseProgram(0);CHECKGLERROR
1240                                         return; // no bit left to clear, entire mode is broken
1241                                 }
1242                         }
1243                 }
1244                 CHECKGLERROR
1245                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1246         }
1247         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1248         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1249         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1250 }
1251
1252 #ifdef SUPPORTD3D
1253
1254 #ifdef SUPPORTD3D
1255 #include <d3d9.h>
1256 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1257 extern D3DCAPS9 vid_d3d9caps;
1258 #endif
1259
1260 struct r_hlsl_permutation_s;
1261 typedef struct r_hlsl_permutation_s
1262 {
1263         /// hash lookup data
1264         struct r_hlsl_permutation_s *hashnext;
1265         unsigned int mode;
1266         unsigned int permutation;
1267
1268         /// indicates if we have tried compiling this permutation already
1269         qboolean compiled;
1270         /// NULL if compilation failed
1271         IDirect3DVertexShader9 *vertexshader;
1272         IDirect3DPixelShader9 *pixelshader;
1273 }
1274 r_hlsl_permutation_t;
1275
1276 typedef enum D3DVSREGISTER_e
1277 {
1278         D3DVSREGISTER_TexMatrix = 0, // float4x4
1279         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1280         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1281         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1282         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1283         D3DVSREGISTER_ModelToLight = 20, // float4x4
1284         D3DVSREGISTER_EyePosition = 24,
1285         D3DVSREGISTER_FogPlane = 25,
1286         D3DVSREGISTER_LightDir = 26,
1287         D3DVSREGISTER_LightPosition = 27,
1288 }
1289 D3DVSREGISTER_t;
1290
1291 typedef enum D3DPSREGISTER_e
1292 {
1293         D3DPSREGISTER_Alpha = 0,
1294         D3DPSREGISTER_BloomBlur_Parameters = 1,
1295         D3DPSREGISTER_ClientTime = 2,
1296         D3DPSREGISTER_Color_Ambient = 3,
1297         D3DPSREGISTER_Color_Diffuse = 4,
1298         D3DPSREGISTER_Color_Specular = 5,
1299         D3DPSREGISTER_Color_Glow = 6,
1300         D3DPSREGISTER_Color_Pants = 7,
1301         D3DPSREGISTER_Color_Shirt = 8,
1302         D3DPSREGISTER_DeferredColor_Ambient = 9,
1303         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1304         D3DPSREGISTER_DeferredColor_Specular = 11,
1305         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1306         D3DPSREGISTER_DeferredMod_Specular = 13,
1307         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1308         D3DPSREGISTER_EyePosition = 15, // unused
1309         D3DPSREGISTER_FogColor = 16,
1310         D3DPSREGISTER_FogHeightFade = 17,
1311         D3DPSREGISTER_FogPlane = 18,
1312         D3DPSREGISTER_FogPlaneViewDist = 19,
1313         D3DPSREGISTER_FogRangeRecip = 20,
1314         D3DPSREGISTER_LightColor = 21,
1315         D3DPSREGISTER_LightDir = 22, // unused
1316         D3DPSREGISTER_LightPosition = 23,
1317         D3DPSREGISTER_OffsetMapping_Scale = 24,
1318         D3DPSREGISTER_PixelSize = 25,
1319         D3DPSREGISTER_ReflectColor = 26,
1320         D3DPSREGISTER_ReflectFactor = 27,
1321         D3DPSREGISTER_ReflectOffset = 28,
1322         D3DPSREGISTER_RefractColor = 29,
1323         D3DPSREGISTER_Saturation = 30,
1324         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1325         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1326         D3DPSREGISTER_ScreenToDepth = 33,
1327         D3DPSREGISTER_ShadowMap_Parameters = 34,
1328         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1329         D3DPSREGISTER_SpecularPower = 36,
1330         D3DPSREGISTER_UserVec1 = 37,
1331         D3DPSREGISTER_UserVec2 = 38,
1332         D3DPSREGISTER_UserVec3 = 39,
1333         D3DPSREGISTER_UserVec4 = 40,
1334         D3DPSREGISTER_ViewTintColor = 41,
1335         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1336         D3DPSREGISTER_BloomColorSubtract = 43,
1337         D3DPSREGISTER_ViewToLight = 44, // float4x4
1338         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1339         D3DPSREGISTER_NormalmapScrollBlend = 52,
1340         // next at 53
1341 }
1342 D3DPSREGISTER_t;
1343
1344 /// information about each possible shader permutation
1345 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1346 /// currently selected permutation
1347 r_hlsl_permutation_t *r_hlsl_permutation;
1348 /// storage for permutations linked in the hash table
1349 memexpandablearray_t r_hlsl_permutationarray;
1350
1351 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1352 {
1353         //unsigned int hashdepth = 0;
1354         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1355         r_hlsl_permutation_t *p;
1356         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1357         {
1358                 if (p->mode == mode && p->permutation == permutation)
1359                 {
1360                         //if (hashdepth > 10)
1361                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1362                         return p;
1363                 }
1364                 //hashdepth++;
1365         }
1366         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1367         p->mode = mode;
1368         p->permutation = permutation;
1369         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1370         r_hlsl_permutationhash[mode][hashindex] = p;
1371         //if (hashdepth > 10)
1372         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1373         return p;
1374 }
1375
1376 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1377 {
1378         char *shaderstring;
1379         if (!filename || !filename[0])
1380                 return NULL;
1381         if (!strcmp(filename, "hlsl/default.hlsl"))
1382         {
1383                 if (!hlslshaderstring)
1384                 {
1385                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1386                         if (hlslshaderstring)
1387                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1388                         else
1389                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1390                 }
1391                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1392                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1393                 return shaderstring;
1394         }
1395         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1396         if (shaderstring)
1397         {
1398                 if (printfromdisknotice)
1399                         Con_DPrintf("from disk %s... ", filename);
1400                 return shaderstring;
1401         }
1402         return shaderstring;
1403 }
1404
1405 #include <d3dx9.h>
1406 //#include <d3dx9shader.h>
1407 //#include <d3dx9mesh.h>
1408
1409 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1410 {
1411         DWORD *vsbin = NULL;
1412         DWORD *psbin = NULL;
1413         fs_offset_t vsbinsize;
1414         fs_offset_t psbinsize;
1415 //      IDirect3DVertexShader9 *vs = NULL;
1416 //      IDirect3DPixelShader9 *ps = NULL;
1417         ID3DXBuffer *vslog = NULL;
1418         ID3DXBuffer *vsbuffer = NULL;
1419         ID3DXConstantTable *vsconstanttable = NULL;
1420         ID3DXBuffer *pslog = NULL;
1421         ID3DXBuffer *psbuffer = NULL;
1422         ID3DXConstantTable *psconstanttable = NULL;
1423         int vsresult = 0;
1424         int psresult = 0;
1425         char temp[MAX_INPUTLINE];
1426         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1427         qboolean debugshader = gl_paranoid.integer != 0;
1428         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1429         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1430         if (!debugshader)
1431         {
1432                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1433                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1434         }
1435         if ((!vsbin && vertstring) || (!psbin && fragstring))
1436         {
1437                 const char* dllnames_d3dx9 [] =
1438                 {
1439                         "d3dx9_43.dll",
1440                         "d3dx9_42.dll",
1441                         "d3dx9_41.dll",
1442                         "d3dx9_40.dll",
1443                         "d3dx9_39.dll",
1444                         "d3dx9_38.dll",
1445                         "d3dx9_37.dll",
1446                         "d3dx9_36.dll",
1447                         "d3dx9_35.dll",
1448                         "d3dx9_34.dll",
1449                         "d3dx9_33.dll",
1450                         "d3dx9_32.dll",
1451                         "d3dx9_31.dll",
1452                         "d3dx9_30.dll",
1453                         "d3dx9_29.dll",
1454                         "d3dx9_28.dll",
1455                         "d3dx9_27.dll",
1456                         "d3dx9_26.dll",
1457                         "d3dx9_25.dll",
1458                         "d3dx9_24.dll",
1459                         NULL
1460                 };
1461                 dllhandle_t d3dx9_dll = NULL;
1462                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1463                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1464                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1465                 dllfunction_t d3dx9_dllfuncs[] =
1466                 {
1467                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1468                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1469                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1470                         {NULL, NULL}
1471                 };
1472                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1473                 {
1474                         DWORD shaderflags = 0;
1475                         if (debugshader)
1476                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1477                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1478                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1479                         if (vertstring && vertstring[0])
1480                         {
1481                                 if (debugshader)
1482                                 {
1483 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1484 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1485                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1486                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1487                                 }
1488                                 else
1489                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1490                                 if (vsbuffer)
1491                                 {
1492                                         vsbinsize = vsbuffer->GetBufferSize();
1493                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1494                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1495                                         vsbuffer->Release();
1496                                 }
1497                                 if (vslog)
1498                                 {
1499                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1500                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1501                                         vslog->Release();
1502                                 }
1503                         }
1504                         if (fragstring && fragstring[0])
1505                         {
1506                                 if (debugshader)
1507                                 {
1508 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1509 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1510                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1511                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1512                                 }
1513                                 else
1514                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1515                                 if (psbuffer)
1516                                 {
1517                                         psbinsize = psbuffer->GetBufferSize();
1518                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1519                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1520                                         psbuffer->Release();
1521                                 }
1522                                 if (pslog)
1523                                 {
1524                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1525                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1526                                         pslog->Release();
1527                                 }
1528                         }
1529                         Sys_UnloadLibrary(&d3dx9_dll);
1530                 }
1531                 else
1532                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1533         }
1534         if (vsbin && psbin)
1535         {
1536                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1537                 if (FAILED(vsresult))
1538                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1539                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1540                 if (FAILED(psresult))
1541                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1542         }
1543         // free the shader data
1544         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1545         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1546 }
1547
1548 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1549 {
1550         int i;
1551         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1552         int vertstring_length = 0;
1553         int geomstring_length = 0;
1554         int fragstring_length = 0;
1555         char *t;
1556         char *vertexstring, *geometrystring, *fragmentstring;
1557         char *vertstring, *geomstring, *fragstring;
1558         char permutationname[256];
1559         char cachename[256];
1560         int vertstrings_count = 0;
1561         int geomstrings_count = 0;
1562         int fragstrings_count = 0;
1563         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1565         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1566
1567         if (p->compiled)
1568                 return;
1569         p->compiled = true;
1570         p->vertexshader = NULL;
1571         p->pixelshader = NULL;
1572
1573         permutationname[0] = 0;
1574         cachename[0] = 0;
1575         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1576         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1577         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1578
1579         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1580         strlcat(cachename, "hlsl/", sizeof(cachename));
1581
1582         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1583         vertstrings_count = 0;
1584         geomstrings_count = 0;
1585         fragstrings_count = 0;
1586         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1587         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1588         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1589
1590         // the first pretext is which type of shader to compile as
1591         // (later these will all be bound together as a program object)
1592         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1593         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1594         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1595
1596         // the second pretext is the mode (for example a light source)
1597         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1598         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1599         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1600         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1601         strlcat(cachename, modeinfo->name, sizeof(cachename));
1602
1603         // now add all the permutation pretexts
1604         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1605         {
1606                 if (permutation & (1<<i))
1607                 {
1608                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1609                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1610                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1611                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1612                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1613                 }
1614                 else
1615                 {
1616                         // keep line numbers correct
1617                         vertstrings_list[vertstrings_count++] = "\n";
1618                         geomstrings_list[geomstrings_count++] = "\n";
1619                         fragstrings_list[fragstrings_count++] = "\n";
1620                 }
1621         }
1622
1623         // add static parms
1624         R_CompileShader_AddStaticParms(mode, permutation);
1625         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1626         vertstrings_count += shaderstaticparms_count;
1627         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1628         geomstrings_count += shaderstaticparms_count;
1629         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1630         fragstrings_count += shaderstaticparms_count;
1631
1632         // replace spaces in the cachename with _ characters
1633         for (i = 0;cachename[i];i++)
1634                 if (cachename[i] == ' ')
1635                         cachename[i] = '_';
1636
1637         // now append the shader text itself
1638         vertstrings_list[vertstrings_count++] = vertexstring;
1639         geomstrings_list[geomstrings_count++] = geometrystring;
1640         fragstrings_list[fragstrings_count++] = fragmentstring;
1641
1642         // if any sources were NULL, clear the respective list
1643         if (!vertexstring)
1644                 vertstrings_count = 0;
1645         if (!geometrystring)
1646                 geomstrings_count = 0;
1647         if (!fragmentstring)
1648                 fragstrings_count = 0;
1649
1650         vertstring_length = 0;
1651         for (i = 0;i < vertstrings_count;i++)
1652                 vertstring_length += strlen(vertstrings_list[i]);
1653         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1654         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1655                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1656
1657         geomstring_length = 0;
1658         for (i = 0;i < geomstrings_count;i++)
1659                 geomstring_length += strlen(geomstrings_list[i]);
1660         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1661         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1662                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1663
1664         fragstring_length = 0;
1665         for (i = 0;i < fragstrings_count;i++)
1666                 fragstring_length += strlen(fragstrings_list[i]);
1667         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1668         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1669                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1670
1671         // try to load the cached shader, or generate one
1672         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1673
1674         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1675                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1676         else
1677                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1678
1679         // free the strings
1680         if (vertstring)
1681                 Mem_Free(vertstring);
1682         if (geomstring)
1683                 Mem_Free(geomstring);
1684         if (fragstring)
1685                 Mem_Free(fragstring);
1686         if (vertexstring)
1687                 Mem_Free(vertexstring);
1688         if (geometrystring)
1689                 Mem_Free(geometrystring);
1690         if (fragmentstring)
1691                 Mem_Free(fragmentstring);
1692 }
1693
1694 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1695 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1696 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);}
1697 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);}
1698 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);}
1699 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);}
1700
1701 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1702 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1703 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);}
1704 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);}
1705 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);}
1706 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);}
1707
1708 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1709 {
1710         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1711         if (r_hlsl_permutation != perm)
1712         {
1713                 r_hlsl_permutation = perm;
1714                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1715                 {
1716                         if (!r_hlsl_permutation->compiled)
1717                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1718                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1719                         {
1720                                 // remove features until we find a valid permutation
1721                                 int i;
1722                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1723                                 {
1724                                         // reduce i more quickly whenever it would not remove any bits
1725                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1726                                         if (!(permutation & j))
1727                                                 continue;
1728                                         permutation -= j;
1729                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1730                                         if (!r_hlsl_permutation->compiled)
1731                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1732                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1733                                                 break;
1734                                 }
1735                                 if (i >= SHADERPERMUTATION_COUNT)
1736                                 {
1737                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1738                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1739                                         return; // no bit left to clear, entire mode is broken
1740                                 }
1741                         }
1742                 }
1743                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1744                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1745         }
1746         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1747         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1748         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1749 }
1750 #endif
1751
1752 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1753 {
1754         DPSOFTRAST_SetShader(mode, permutation);
1755         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1756         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1757         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1758 }
1759
1760 void R_GLSL_Restart_f(void)
1761 {
1762         unsigned int i, limit;
1763         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1764                 Mem_Free(glslshaderstring);
1765         glslshaderstring = NULL;
1766         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1767                 Mem_Free(hlslshaderstring);
1768         hlslshaderstring = NULL;
1769         switch(vid.renderpath)
1770         {
1771         case RENDERPATH_D3D9:
1772 #ifdef SUPPORTD3D
1773                 {
1774                         r_hlsl_permutation_t *p;
1775                         r_hlsl_permutation = NULL;
1776                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1777                         for (i = 0;i < limit;i++)
1778                         {
1779                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1780                                 {
1781                                         if (p->vertexshader)
1782                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1783                                         if (p->pixelshader)
1784                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1785                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1786                                 }
1787                         }
1788                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1789                 }
1790 #endif
1791                 break;
1792         case RENDERPATH_D3D10:
1793                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1794                 break;
1795         case RENDERPATH_D3D11:
1796                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1797                 break;
1798         case RENDERPATH_GL20:
1799         case RENDERPATH_GLES2:
1800                 {
1801                         r_glsl_permutation_t *p;
1802                         r_glsl_permutation = NULL;
1803                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1804                         for (i = 0;i < limit;i++)
1805                         {
1806                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1807                                 {
1808                                         GL_Backend_FreeProgram(p->program);
1809                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1810                                 }
1811                         }
1812                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1813                 }
1814                 break;
1815         case RENDERPATH_GL13:
1816         case RENDERPATH_GL11:
1817                 break;
1818         case RENDERPATH_SOFT:
1819                 break;
1820         }
1821 }
1822
1823 void R_GLSL_DumpShader_f(void)
1824 {
1825         int i;
1826         qfile_t *file;
1827
1828         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1829         if (file)
1830         {
1831                 FS_Print(file, "/* The engine may define the following macros:\n");
1832                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1833                 for (i = 0;i < SHADERMODE_COUNT;i++)
1834                         FS_Print(file, glslshadermodeinfo[i].pretext);
1835                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1836                         FS_Print(file, shaderpermutationinfo[i].pretext);
1837                 FS_Print(file, "*/\n");
1838                 FS_Print(file, builtinshaderstring);
1839                 FS_Close(file);
1840                 Con_Printf("glsl/default.glsl written\n");
1841         }
1842         else
1843                 Con_Printf("failed to write to glsl/default.glsl\n");
1844
1845         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1846         if (file)
1847         {
1848                 FS_Print(file, "/* The engine may define the following macros:\n");
1849                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1850                 for (i = 0;i < SHADERMODE_COUNT;i++)
1851                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1852                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1853                         FS_Print(file, shaderpermutationinfo[i].pretext);
1854                 FS_Print(file, "*/\n");
1855                 FS_Print(file, builtinhlslshaderstring);
1856                 FS_Close(file);
1857                 Con_Printf("hlsl/default.hlsl written\n");
1858         }
1859         else
1860                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1861 }
1862
1863 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1864 {
1865         if (!second)
1866                 texturemode = GL_MODULATE;
1867         switch (vid.renderpath)
1868         {
1869         case RENDERPATH_D3D9:
1870 #ifdef SUPPORTD3D
1871                 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))));
1872                 R_Mesh_TexBind(GL20TU_FIRST , first );
1873                 R_Mesh_TexBind(GL20TU_SECOND, second);
1874 #endif
1875                 break;
1876         case RENDERPATH_D3D10:
1877                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1878                 break;
1879         case RENDERPATH_D3D11:
1880                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1881                 break;
1882         case RENDERPATH_GL20:
1883         case RENDERPATH_GLES2:
1884                 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))));
1885                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1886                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1887                 break;
1888         case RENDERPATH_GL13:
1889                 R_Mesh_TexBind(0, first );
1890                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1891                 R_Mesh_TexBind(1, second);
1892                 if (second)
1893                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1894                 break;
1895         case RENDERPATH_GL11:
1896                 R_Mesh_TexBind(0, first );
1897                 break;
1898         case RENDERPATH_SOFT:
1899                 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))));
1900                 R_Mesh_TexBind(GL20TU_FIRST , first );
1901                 R_Mesh_TexBind(GL20TU_SECOND, second);
1902                 break;
1903         }
1904 }
1905
1906 void R_SetupShader_DepthOrShadow(void)
1907 {
1908         switch (vid.renderpath)
1909         {
1910         case RENDERPATH_D3D9:
1911 #ifdef SUPPORTD3D
1912                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1913 #endif
1914                 break;
1915         case RENDERPATH_D3D10:
1916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917                 break;
1918         case RENDERPATH_D3D11:
1919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_GL20:
1922         case RENDERPATH_GLES2:
1923                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1924                 break;
1925         case RENDERPATH_GL13:
1926                 R_Mesh_TexBind(0, 0);
1927                 R_Mesh_TexBind(1, 0);
1928                 break;
1929         case RENDERPATH_GL11:
1930                 R_Mesh_TexBind(0, 0);
1931                 break;
1932         case RENDERPATH_SOFT:
1933                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1934                 break;
1935         }
1936 }
1937
1938 void R_SetupShader_ShowDepth(void)
1939 {
1940         switch (vid.renderpath)
1941         {
1942         case RENDERPATH_D3D9:
1943 #ifdef SUPPORTHLSL
1944                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1945 #endif
1946                 break;
1947         case RENDERPATH_D3D10:
1948                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949                 break;
1950         case RENDERPATH_D3D11:
1951                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_GL20:
1954         case RENDERPATH_GLES2:
1955                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1956                 break;
1957         case RENDERPATH_GL13:
1958                 break;
1959         case RENDERPATH_GL11:
1960                 break;
1961         case RENDERPATH_SOFT:
1962                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1963                 break;
1964         }
1965 }
1966
1967 extern qboolean r_shadow_usingdeferredprepass;
1968 extern cvar_t r_shadow_deferred_8bitrange;
1969 extern rtexture_t *r_shadow_attenuationgradienttexture;
1970 extern rtexture_t *r_shadow_attenuation2dtexture;
1971 extern rtexture_t *r_shadow_attenuation3dtexture;
1972 extern qboolean r_shadow_usingshadowmap2d;
1973 extern qboolean r_shadow_usingshadowmaportho;
1974 extern float r_shadow_shadowmap_texturescale[2];
1975 extern float r_shadow_shadowmap_parameters[4];
1976 extern qboolean r_shadow_shadowmapvsdct;
1977 extern qboolean r_shadow_shadowmapsampler;
1978 extern int r_shadow_shadowmappcf;
1979 extern rtexture_t *r_shadow_shadowmap2dtexture;
1980 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1981 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1982 extern matrix4x4_t r_shadow_shadowmapmatrix;
1983 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1984 extern int r_shadow_prepass_width;
1985 extern int r_shadow_prepass_height;
1986 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1987 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1988 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1989 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1990 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1991
1992 #define BLENDFUNC_ALLOWS_COLORMOD      1
1993 #define BLENDFUNC_ALLOWS_FOG           2
1994 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
1995 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
1996 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
1997 static int R_BlendFuncFlags(int src, int dst)
1998 {
1999         int r = 0;
2000
2001         // a blendfunc allows colormod if:
2002         // a) it can never keep the destination pixel invariant, or
2003         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2004         // this is to prevent unintended side effects from colormod
2005
2006         // a blendfunc allows fog if:
2007         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2008         // this is to prevent unintended side effects from fog
2009
2010         // these checks are the output of fogeval.pl
2011
2012         r |= BLENDFUNC_ALLOWS_COLORMOD;
2013         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2014         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2015         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2016         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2017         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2018         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2019         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2020         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2021         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2022         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2023         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2024         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2025         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2026         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2027         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2028         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2031         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2032         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2033         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2034
2035         return r;
2036 }
2037
2038 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)
2039 {
2040         // select a permutation of the lighting shader appropriate to this
2041         // combination of texture, entity, light source, and fogging, only use the
2042         // minimum features necessary to avoid wasting rendering time in the
2043         // fragment shader on features that are not being used
2044         unsigned int permutation = 0;
2045         unsigned int mode = 0;
2046         int blendfuncflags;
2047         static float dummy_colormod[3] = {1, 1, 1};
2048         float *colormod = rsurface.colormod;
2049         float m16f[16];
2050         matrix4x4_t tempmatrix;
2051         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2052         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2053                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2054         if (rsurfacepass == RSURFPASS_BACKGROUND)
2055         {
2056                 // distorted background
2057                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2058                 {
2059                         mode = SHADERMODE_WATER;
2060                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2061                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2062                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2063                         {
2064                                 // this is the right thing to do for wateralpha
2065                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2066                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2067                         }
2068                         else
2069                         {
2070                                 // this is the right thing to do for entity alpha
2071                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2072                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2073                         }
2074                 }
2075                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2076                 {
2077                         mode = SHADERMODE_REFRACTION;
2078                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2079                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2080                 }
2081                 else
2082                 {
2083                         mode = SHADERMODE_GENERIC;
2084                         permutation |= SHADERPERMUTATION_DIFFUSE;
2085                         GL_BlendFunc(GL_ONE, GL_ZERO);
2086                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2087                 }
2088         }
2089         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2090         {
2091                 if (r_glsl_offsetmapping.integer)
2092                 {
2093                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2094                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2095                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2096                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2097                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2098                         {
2099                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2100                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2101                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2102                         }
2103                 }
2104                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2105                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2106                 // normalmap (deferred prepass), may use alpha test on diffuse
2107                 mode = SHADERMODE_DEFERREDGEOMETRY;
2108                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2109                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2110                 GL_BlendFunc(GL_ONE, GL_ZERO);
2111                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2112         }
2113         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2114         {
2115                 if (r_glsl_offsetmapping.integer)
2116                 {
2117                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2118                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2119                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2120                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2121                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2122                         {
2123                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2124                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2125                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2126                         }
2127                 }
2128                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2129                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2130                 // light source
2131                 mode = SHADERMODE_LIGHTSOURCE;
2132                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2133                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2134                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2135                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2136                 if (diffusescale > 0)
2137                         permutation |= SHADERPERMUTATION_DIFFUSE;
2138                 if (specularscale > 0)
2139                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2140                 if (r_refdef.fogenabled)
2141                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2142                 if (rsurface.texture->colormapping)
2143                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2144                 if (r_shadow_usingshadowmap2d)
2145                 {
2146                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2147                         if(r_shadow_shadowmapvsdct)
2148                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2149
2150                         if (r_shadow_shadowmapsampler)
2151                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2152                         if (r_shadow_shadowmappcf > 1)
2153                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2154                         else if (r_shadow_shadowmappcf)
2155                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2156                 }
2157                 if (rsurface.texture->reflectmasktexture)
2158                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2159                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2160                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2161         }
2162         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2163         {
2164                 if (r_glsl_offsetmapping.integer)
2165                 {
2166                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2167                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2168                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2169                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2170                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2171                         {
2172                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2173                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2174                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2175                         }
2176                 }
2177                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2178                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2179                 // unshaded geometry (fullbright or ambient model lighting)
2180                 mode = SHADERMODE_FLATCOLOR;
2181                 ambientscale = diffusescale = specularscale = 0;
2182                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2183                         permutation |= SHADERPERMUTATION_GLOW;
2184                 if (r_refdef.fogenabled)
2185                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2186                 if (rsurface.texture->colormapping)
2187                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2188                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2189                 {
2190                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2191                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2192
2193                         if (r_shadow_shadowmapsampler)
2194                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2195                         if (r_shadow_shadowmappcf > 1)
2196                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2197                         else if (r_shadow_shadowmappcf)
2198                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2199                 }
2200                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2201                         permutation |= SHADERPERMUTATION_REFLECTION;
2202                 if (rsurface.texture->reflectmasktexture)
2203                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2204                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2205                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2206         }
2207         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2208         {
2209                 if (r_glsl_offsetmapping.integer)
2210                 {
2211                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2212                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2213                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2214                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2215                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2216                         {
2217                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2218                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2219                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2220                         }
2221                 }
2222                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2223                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2224                 // directional model lighting
2225                 mode = SHADERMODE_LIGHTDIRECTION;
2226                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2227                         permutation |= SHADERPERMUTATION_GLOW;
2228                 permutation |= SHADERPERMUTATION_DIFFUSE;
2229                 if (specularscale > 0)
2230                         permutation |= SHADERPERMUTATION_SPECULAR;
2231                 if (r_refdef.fogenabled)
2232                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2233                 if (rsurface.texture->colormapping)
2234                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2235                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2236                 {
2237                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2238                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2239
2240                         if (r_shadow_shadowmapsampler)
2241                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2242                         if (r_shadow_shadowmappcf > 1)
2243                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2244                         else if (r_shadow_shadowmappcf)
2245                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2246                 }
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2248                         permutation |= SHADERPERMUTATION_REFLECTION;
2249                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2250                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2251                 if (rsurface.texture->reflectmasktexture)
2252                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2253                 if (r_shadow_bouncegridtexture)
2254                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2255                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2256                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2257         }
2258         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
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                 // ambient model lighting
2276                 mode = SHADERMODE_LIGHTDIRECTION;
2277                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278                         permutation |= SHADERPERMUTATION_GLOW;
2279                 if (r_refdef.fogenabled)
2280                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2281                 if (rsurface.texture->colormapping)
2282                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2283                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2284                 {
2285                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2286                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2287
2288                         if (r_shadow_shadowmapsampler)
2289                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2290                         if (r_shadow_shadowmappcf > 1)
2291                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2292                         else if (r_shadow_shadowmappcf)
2293                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2294                 }
2295                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2296                         permutation |= SHADERPERMUTATION_REFLECTION;
2297                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2298                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2299                 if (rsurface.texture->reflectmasktexture)
2300                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2301                 if (r_shadow_bouncegridtexture)
2302                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2303                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2305         }
2306         else
2307         {
2308                 if (r_glsl_offsetmapping.integer)
2309                 {
2310                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2311                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2312                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2313                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2314                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2315                         {
2316                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2317                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2318                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2319                         }
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323                 // lightmapped wall
2324                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2325                         permutation |= SHADERPERMUTATION_GLOW;
2326                 if (r_refdef.fogenabled)
2327                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2328                 if (rsurface.texture->colormapping)
2329                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2330                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2331                 {
2332                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2333                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2334
2335                         if (r_shadow_shadowmapsampler)
2336                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2337                         if (r_shadow_shadowmappcf > 1)
2338                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2339                         else if (r_shadow_shadowmappcf)
2340                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2341                 }
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2343                         permutation |= SHADERPERMUTATION_REFLECTION;
2344                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2345                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2346                 if (rsurface.texture->reflectmasktexture)
2347                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348                 if (FAKELIGHT_ENABLED)
2349                 {
2350                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2351                         mode = SHADERMODE_FAKELIGHT;
2352                         permutation |= SHADERPERMUTATION_DIFFUSE;
2353                         if (specularscale > 0)
2354                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2355                 }
2356                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2357                 {
2358                         // deluxemapping (light direction texture)
2359                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2360                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2361                         else
2362                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2363                         permutation |= SHADERPERMUTATION_DIFFUSE;
2364                         if (specularscale > 0)
2365                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2366                 }
2367                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2368                 {
2369                         // fake deluxemapping (uniform light direction in tangentspace)
2370                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2371                         permutation |= SHADERPERMUTATION_DIFFUSE;
2372                         if (specularscale > 0)
2373                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2374                 }
2375                 else if (rsurface.uselightmaptexture)
2376                 {
2377                         // ordinary lightmapping (q1bsp, q3bsp)
2378                         mode = SHADERMODE_LIGHTMAP;
2379                 }
2380                 else
2381                 {
2382                         // ordinary vertex coloring (q3bsp)
2383                         mode = SHADERMODE_VERTEXCOLOR;
2384                 }
2385                 if (r_shadow_bouncegridtexture)
2386                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389         }
2390         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2391                 colormod = dummy_colormod;
2392         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2393                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2394         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2395                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2396         switch(vid.renderpath)
2397         {
2398         case RENDERPATH_D3D9:
2399 #ifdef SUPPORTD3D
2400                 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);
2401                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2402                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2403                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2404                 if (mode == SHADERMODE_LIGHTSOURCE)
2405                 {
2406                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2407                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2408                 }
2409                 else
2410                 {
2411                         if (mode == SHADERMODE_LIGHTDIRECTION)
2412                         {
2413                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2414                         }
2415                 }
2416                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2417                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2418                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2419                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2420                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2421
2422                 if (mode == SHADERMODE_LIGHTSOURCE)
2423                 {
2424                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2425                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2426                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2427                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2428                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2429
2430                         // additive passes are only darkened by fog, not tinted
2431                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2432                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2433                 }
2434                 else
2435                 {
2436                         if (mode == SHADERMODE_FLATCOLOR)
2437                         {
2438                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2439                         }
2440                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2441                         {
2442                                 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]);
2443                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2444                                 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);
2445                                 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);
2446                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2447                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2448                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2449                         }
2450                         else
2451                         {
2452                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2453                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2454                                 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);
2455                                 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);
2456                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2457                         }
2458                         // additive passes are only darkened by fog, not tinted
2459                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2460                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2461                         else
2462                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2463                         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);
2464                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2465                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2466                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2467                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2468                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2469                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2470                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2471                         if (mode == SHADERMODE_WATER)
2472                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2473                 }
2474                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2475                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2476                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2477                 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));
2478                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2479                 if (rsurface.texture->pantstexture)
2480                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2481                 else
2482                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2483                 if (rsurface.texture->shirttexture)
2484                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2485                 else
2486                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2487                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2488                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2489                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2490                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2491                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2492                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2493                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2494
2495                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2496                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2497                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2498                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2499                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2500                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2501                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2502                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2503                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2504                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2505                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2506                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2507                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2508                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2509                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2510                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2511                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2512                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2513                 {
2514                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2515                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2516                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2517                 }
2518                 else
2519                 {
2520                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2521                 }
2522 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2523 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2524                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2525                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2526                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2527                 {
2528                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2529                         if (rsurface.rtlight)
2530                         {
2531                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2532                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2533                         }
2534                 }
2535 #endif
2536                 break;
2537         case RENDERPATH_D3D10:
2538                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2539                 break;
2540         case RENDERPATH_D3D11:
2541                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2542                 break;
2543         case RENDERPATH_GL20:
2544         case RENDERPATH_GLES2:
2545                 if (!vid.useinterleavedarrays)
2546                 {
2547                         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);
2548                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2549                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2550                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2551                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2552                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2553                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2554                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2555                 }
2556                 else
2557                 {
2558                         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);
2559                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2560                 }
2561                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2562                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2563                 if (mode == SHADERMODE_LIGHTSOURCE)
2564                 {
2565                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2566                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2567                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2568                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2569                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2570                         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);
2571         
2572                         // additive passes are only darkened by fog, not tinted
2573                         if (r_glsl_permutation->loc_FogColor >= 0)
2574                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2575                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2576                 }
2577                 else
2578                 {
2579                         if (mode == SHADERMODE_FLATCOLOR)
2580                         {
2581                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2582                         }
2583                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2584                         {
2585                                 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]);
2586                                 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]);
2587                                 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);
2588                                 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);
2589                                 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);
2590                                 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]);
2591                                 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]);
2592                         }
2593                         else
2594                         {
2595                                 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]);
2596                                 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]);
2597                                 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);
2598                                 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);
2599                                 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);
2600                         }
2601                         // additive passes are only darkened by fog, not tinted
2602                         if (r_glsl_permutation->loc_FogColor >= 0)
2603                         {
2604                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2605                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2606                                 else
2607                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2608                         }
2609                         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);
2610                         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]);
2611                         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]);
2612                         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]);
2613                         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]);
2614                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2615                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2616                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2617                         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]);
2618                 }
2619                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2620                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2621                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2622                 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]);
2623                 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]);
2624
2625                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2626                 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));
2627                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2628                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2629                 {
2630                         if (rsurface.texture->pantstexture)
2631                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2632                         else
2633                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2634                 }
2635                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2636                 {
2637                         if (rsurface.texture->shirttexture)
2638                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2639                         else
2640                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2641                 }
2642                 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]);
2643                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2644                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2645                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2646                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2647                 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]);
2648                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2649                 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);}
2650                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2651
2652                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2653                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2654                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2655                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2656                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2657                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2658                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2659                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2660                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2661                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2662                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2663                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2664                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2665                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2666                 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);
2667                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2668                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2669                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2670                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2671                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2672                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2673                 {
2674                         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);
2675                         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);
2676                         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);
2677                 }
2678                 else
2679                 {
2680                         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);
2681                 }
2682                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2683                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2684                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2685                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2686                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2687                 {
2688                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2689                         if (rsurface.rtlight)
2690                         {
2691                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2692                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2693                         }
2694                 }
2695                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2696                 CHECKGLERROR
2697                 break;
2698         case RENDERPATH_GL13:
2699         case RENDERPATH_GL11:
2700                 break;
2701         case RENDERPATH_SOFT:
2702                 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);
2703                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2704                 R_SetupShader_SetPermutationSoft(mode, permutation);
2705                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2706                 if (mode == SHADERMODE_LIGHTSOURCE)
2707                 {
2708                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2709                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2710                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2711                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2712                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2713                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2714         
2715                         // additive passes are only darkened by fog, not tinted
2716                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2717                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2718                 }
2719                 else
2720                 {
2721                         if (mode == SHADERMODE_FLATCOLOR)
2722                         {
2723                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2724                         }
2725                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2726                         {
2727                                 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]);
2728                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2729                                 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);
2730                                 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);
2731                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2732                                 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]);
2733                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2734                         }
2735                         else
2736                         {
2737                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2738                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2739                                 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);
2740                                 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);
2741                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2742                         }
2743                         // additive passes are only darkened by fog, not tinted
2744                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2746                         else
2747                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748                         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);
2749                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2750                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2751                         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]);
2752                         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]);
2753                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2754                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2755                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2756                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2757                 }
2758                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2759                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2760                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2761                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2762                 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]);
2763
2764                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2765                 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));
2766                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2767                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2768                 {
2769                         if (rsurface.texture->pantstexture)
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2771                         else
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2773                 }
2774                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2775                 {
2776                         if (rsurface.texture->shirttexture)
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2778                         else
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2780                 }
2781                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2782                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2783                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2784                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2785                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2786                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2787                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2788
2789                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2790                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2791                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2792                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2793                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2794                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2795                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2796                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2797                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2798                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2799                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2800                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2801                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2802                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2803                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2804                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2805                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2806                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2807                 {
2808                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2809                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2810                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2811                 }
2812                 else
2813                 {
2814                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2815                 }
2816 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2817 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2818                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2819                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2820                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2821                 {
2822                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2823                         if (rsurface.rtlight)
2824                         {
2825                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2826                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2827                         }
2828                 }
2829                 break;
2830         }
2831 }
2832
2833 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2834 {
2835         // select a permutation of the lighting shader appropriate to this
2836         // combination of texture, entity, light source, and fogging, only use the
2837         // minimum features necessary to avoid wasting rendering time in the
2838         // fragment shader on features that are not being used
2839         unsigned int permutation = 0;
2840         unsigned int mode = 0;
2841         const float *lightcolorbase = rtlight->currentcolor;
2842         float ambientscale = rtlight->ambientscale;
2843         float diffusescale = rtlight->diffusescale;
2844         float specularscale = rtlight->specularscale;
2845         // this is the location of the light in view space
2846         vec3_t viewlightorigin;
2847         // this transforms from view space (camera) to light space (cubemap)
2848         matrix4x4_t viewtolight;
2849         matrix4x4_t lighttoview;
2850         float viewtolight16f[16];
2851         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2852         // light source
2853         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2854         if (rtlight->currentcubemap != r_texture_whitecube)
2855                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2856         if (diffusescale > 0)
2857                 permutation |= SHADERPERMUTATION_DIFFUSE;
2858         if (specularscale > 0)
2859                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2860         if (r_shadow_usingshadowmap2d)
2861         {
2862                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2863                 if (r_shadow_shadowmapvsdct)
2864                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2865
2866                 if (r_shadow_shadowmapsampler)
2867                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2868                 if (r_shadow_shadowmappcf > 1)
2869                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2870                 else if (r_shadow_shadowmappcf)
2871                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2872         }
2873         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2874         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2875         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2876         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2877         switch(vid.renderpath)
2878         {
2879         case RENDERPATH_D3D9:
2880 #ifdef SUPPORTD3D
2881                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2882                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2883                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2884                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2885                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2886                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2887                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2888                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2889                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2890                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2891                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2892
2893                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2894                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2895                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2896                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2897                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2898                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2899 #endif
2900                 break;
2901         case RENDERPATH_D3D10:
2902                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2903                 break;
2904         case RENDERPATH_D3D11:
2905                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2906                 break;
2907         case RENDERPATH_GL20:
2908         case RENDERPATH_GLES2:
2909                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2910                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2911                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2912                 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);
2913                 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);
2914                 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);
2915                 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]);
2916                 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]);
2917                 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));
2918                 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]);
2919                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2920
2921                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2922                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2923                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2924                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2925                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2926                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2927                 break;
2928         case RENDERPATH_GL13:
2929         case RENDERPATH_GL11:
2930                 break;
2931         case RENDERPATH_SOFT:
2932                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2933                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2934                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2935                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2936                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2937                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2938                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2939                 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]);
2940                 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));
2941                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2945                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2946                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2947                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2948                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2949                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2950                 break;
2951         }
2952 }
2953
2954 #define SKINFRAME_HASH 1024
2955
2956 typedef struct
2957 {
2958         int loadsequence; // incremented each level change
2959         memexpandablearray_t array;
2960         skinframe_t *hash[SKINFRAME_HASH];
2961 }
2962 r_skinframe_t;
2963 r_skinframe_t r_skinframe;
2964
2965 void R_SkinFrame_PrepareForPurge(void)
2966 {
2967         r_skinframe.loadsequence++;
2968         // wrap it without hitting zero
2969         if (r_skinframe.loadsequence >= 200)
2970                 r_skinframe.loadsequence = 1;
2971 }
2972
2973 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2974 {
2975         if (!skinframe)
2976                 return;
2977         // mark the skinframe as used for the purging code
2978         skinframe->loadsequence = r_skinframe.loadsequence;
2979 }
2980
2981 void R_SkinFrame_Purge(void)
2982 {
2983         int i;
2984         skinframe_t *s;
2985         for (i = 0;i < SKINFRAME_HASH;i++)
2986         {
2987                 for (s = r_skinframe.hash[i];s;s = s->next)
2988                 {
2989                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2990                         {
2991                                 if (s->merged == s->base)
2992                                         s->merged = NULL;
2993                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2994                                 R_PurgeTexture(s->stain );s->stain  = NULL;
2995                                 R_PurgeTexture(s->merged);s->merged = NULL;
2996                                 R_PurgeTexture(s->base  );s->base   = NULL;
2997                                 R_PurgeTexture(s->pants );s->pants  = NULL;
2998                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
2999                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3000                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3001                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3002                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3003                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3004                                 s->loadsequence = 0;
3005                         }
3006                 }
3007         }
3008 }
3009
3010 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3011         skinframe_t *item;
3012         char basename[MAX_QPATH];
3013
3014         Image_StripImageExtension(name, basename, sizeof(basename));
3015
3016         if( last == NULL ) {
3017                 int hashindex;
3018                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3019                 item = r_skinframe.hash[hashindex];
3020         } else {
3021                 item = last->next;
3022         }
3023
3024         // linearly search through the hash bucket
3025         for( ; item ; item = item->next ) {
3026                 if( !strcmp( item->basename, basename ) ) {
3027                         return item;
3028                 }
3029         }
3030         return NULL;
3031 }
3032
3033 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3034 {
3035         skinframe_t *item;
3036         int hashindex;
3037         char basename[MAX_QPATH];
3038
3039         Image_StripImageExtension(name, basename, sizeof(basename));
3040
3041         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3042         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3043                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3044                         break;
3045
3046         if (!item) {
3047                 rtexture_t *dyntexture;
3048                 // check whether its a dynamic texture
3049                 dyntexture = CL_GetDynTexture( basename );
3050                 if (!add && !dyntexture)
3051                         return NULL;
3052                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3053                 memset(item, 0, sizeof(*item));
3054                 strlcpy(item->basename, basename, sizeof(item->basename));
3055                 item->base = dyntexture; // either NULL or dyntexture handle
3056                 item->textureflags = textureflags;
3057                 item->comparewidth = comparewidth;
3058                 item->compareheight = compareheight;
3059                 item->comparecrc = comparecrc;
3060                 item->next = r_skinframe.hash[hashindex];
3061                 r_skinframe.hash[hashindex] = item;
3062         }
3063         else if( item->base == NULL )
3064         {
3065                 rtexture_t *dyntexture;
3066                 // check whether its a dynamic texture
3067                 // 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]
3068                 dyntexture = CL_GetDynTexture( basename );
3069                 item->base = dyntexture; // either NULL or dyntexture handle
3070         }
3071
3072         R_SkinFrame_MarkUsed(item);
3073         return item;
3074 }
3075
3076 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3077         { \
3078                 unsigned long long avgcolor[5], wsum; \
3079                 int pix, comp, w; \
3080                 avgcolor[0] = 0; \
3081                 avgcolor[1] = 0; \
3082                 avgcolor[2] = 0; \
3083                 avgcolor[3] = 0; \
3084                 avgcolor[4] = 0; \
3085                 wsum = 0; \
3086                 for(pix = 0; pix < cnt; ++pix) \
3087                 { \
3088                         w = 0; \
3089                         for(comp = 0; comp < 3; ++comp) \
3090                                 w += getpixel; \
3091                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3092                         { \
3093                                 ++wsum; \
3094                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3095                                 w = getpixel; \
3096                                 for(comp = 0; comp < 3; ++comp) \
3097                                         avgcolor[comp] += getpixel * w; \
3098                                 avgcolor[3] += w; \
3099                         } \
3100                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3101                         avgcolor[4] += getpixel; \
3102                 } \
3103                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3104                         avgcolor[3] = 1; \
3105                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3106                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3107                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3108                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3109         }
3110
3111 extern cvar_t gl_picmip;
3112 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3113 {
3114         int j;
3115         unsigned char *pixels;
3116         unsigned char *bumppixels;
3117         unsigned char *basepixels = NULL;
3118         int basepixels_width = 0;
3119         int basepixels_height = 0;
3120         skinframe_t *skinframe;
3121         rtexture_t *ddsbase = NULL;
3122         qboolean ddshasalpha = false;
3123         float ddsavgcolor[4];
3124         char basename[MAX_QPATH];
3125         int miplevel = R_PicmipForFlags(textureflags);
3126         int savemiplevel = miplevel;
3127         int mymiplevel;
3128
3129         if (cls.state == ca_dedicated)
3130                 return NULL;
3131
3132         // return an existing skinframe if already loaded
3133         // if loading of the first image fails, don't make a new skinframe as it
3134         // would cause all future lookups of this to be missing
3135         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3136         if (skinframe && skinframe->base)
3137                 return skinframe;
3138
3139         Image_StripImageExtension(name, basename, sizeof(basename));
3140
3141         // check for DDS texture file first
3142         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3143         {
3144                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3145                 if (basepixels == NULL)
3146                         return NULL;
3147         }
3148
3149         // FIXME handle miplevel
3150
3151         if (developer_loading.integer)
3152                 Con_Printf("loading skin \"%s\"\n", name);
3153
3154         // we've got some pixels to store, so really allocate this new texture now
3155         if (!skinframe)
3156                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3157         skinframe->stain = NULL;
3158         skinframe->merged = NULL;
3159         skinframe->base = NULL;
3160         skinframe->pants = NULL;
3161         skinframe->shirt = NULL;
3162         skinframe->nmap = NULL;
3163         skinframe->gloss = NULL;
3164         skinframe->glow = NULL;
3165         skinframe->fog = NULL;
3166         skinframe->reflect = NULL;
3167         skinframe->hasalpha = false;
3168
3169         if (ddsbase)
3170         {
3171                 skinframe->base = ddsbase;
3172                 skinframe->hasalpha = ddshasalpha;
3173                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3174                 if (r_loadfog && skinframe->hasalpha)
3175                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3176                 //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]);
3177         }
3178         else
3179         {
3180                 basepixels_width = image_width;
3181                 basepixels_height = image_height;
3182                 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);
3183                 if (textureflags & TEXF_ALPHA)
3184                 {
3185                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3186                         {
3187                                 if (basepixels[j] < 255)
3188                                 {
3189                                         skinframe->hasalpha = true;
3190                                         break;
3191                                 }
3192                         }
3193                         if (r_loadfog && skinframe->hasalpha)
3194                         {
3195                                 // has transparent pixels
3196                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3197                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3198                                 {
3199                                         pixels[j+0] = 255;
3200                                         pixels[j+1] = 255;
3201                                         pixels[j+2] = 255;
3202                                         pixels[j+3] = basepixels[j+3];
3203                                 }
3204                                 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);
3205                                 Mem_Free(pixels);
3206                         }
3207                 }
3208                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3209                 //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]);
3210                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3211                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3212                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3213                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3214         }
3215
3216         if (r_loaddds)
3217         {
3218                 mymiplevel = savemiplevel;
3219                 if (r_loadnormalmap)
3220                         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);
3221                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3222                 if (r_loadgloss)
3223                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3224                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3225                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3226                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3227         }
3228
3229         // _norm is the name used by tenebrae and has been adopted as standard
3230         if (r_loadnormalmap && skinframe->nmap == NULL)
3231         {
3232                 mymiplevel = savemiplevel;
3233                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3234                 {
3235                         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);
3236                         Mem_Free(pixels);
3237                         pixels = NULL;
3238                 }
3239                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3240                 {
3241                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3242                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3243                         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);
3244                         Mem_Free(pixels);
3245                         Mem_Free(bumppixels);
3246                 }
3247                 else if (r_shadow_bumpscale_basetexture.value > 0)
3248                 {
3249                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3250                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3251                         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);
3252                         Mem_Free(pixels);
3253                 }
3254                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3255                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3256         }
3257
3258         // _luma is supported only for tenebrae compatibility
3259         // _glow is the preferred name
3260         mymiplevel = savemiplevel;
3261         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))))
3262         {
3263                 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);
3264                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3265                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3266                 Mem_Free(pixels);pixels = NULL;
3267         }
3268
3269         mymiplevel = savemiplevel;
3270         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3271         {
3272                 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);
3273                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3274                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3275                 Mem_Free(pixels);
3276                 pixels = NULL;
3277         }
3278
3279         mymiplevel = savemiplevel;
3280         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3281         {
3282                 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);
3283                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3284                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3285                 Mem_Free(pixels);
3286                 pixels = NULL;
3287         }
3288
3289         mymiplevel = savemiplevel;
3290         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3291         {
3292                 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);
3293                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3294                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3295                 Mem_Free(pixels);
3296                 pixels = NULL;
3297         }
3298
3299         mymiplevel = savemiplevel;
3300         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3301         {
3302                 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);
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3304                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3305                 Mem_Free(pixels);
3306                 pixels = NULL;
3307         }
3308
3309         if (basepixels)
3310                 Mem_Free(basepixels);
3311
3312         return skinframe;
3313 }
3314
3315 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3316 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3317 {
3318         int i;
3319         unsigned char *temp1, *temp2;
3320         skinframe_t *skinframe;
3321
3322         if (cls.state == ca_dedicated)
3323                 return NULL;
3324
3325         // if already loaded just return it, otherwise make a new skinframe
3326         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3327         if (skinframe && skinframe->base)
3328                 return skinframe;
3329
3330         skinframe->stain = NULL;
3331         skinframe->merged = NULL;
3332         skinframe->base = NULL;
3333         skinframe->pants = NULL;
3334         skinframe->shirt = NULL;
3335         skinframe->nmap = NULL;
3336         skinframe->gloss = NULL;
3337         skinframe->glow = NULL;
3338         skinframe->fog = NULL;
3339         skinframe->reflect = NULL;
3340         skinframe->hasalpha = false;
3341
3342         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3343         if (!skindata)
3344                 return NULL;
3345
3346         if (developer_loading.integer)
3347                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3348
3349         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3350         {
3351                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3352                 temp2 = temp1 + width * height * 4;
3353                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3354                 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);
3355                 Mem_Free(temp1);
3356         }
3357         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3358         if (textureflags & TEXF_ALPHA)
3359         {
3360                 for (i = 3;i < width * height * 4;i += 4)
3361                 {
3362                         if (skindata[i] < 255)
3363                         {
3364                                 skinframe->hasalpha = true;
3365                                 break;
3366                         }
3367                 }
3368                 if (r_loadfog && skinframe->hasalpha)
3369                 {
3370                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3371                         memcpy(fogpixels, skindata, width * height * 4);
3372                         for (i = 0;i < width * height * 4;i += 4)
3373                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3374                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3375                         Mem_Free(fogpixels);
3376                 }
3377         }
3378
3379         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3380         //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]);
3381
3382         return skinframe;
3383 }
3384
3385 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3386 {
3387         int i;
3388         int featuresmask;
3389         skinframe_t *skinframe;
3390
3391         if (cls.state == ca_dedicated)
3392                 return NULL;
3393
3394         // if already loaded just return it, otherwise make a new skinframe
3395         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3396         if (skinframe && skinframe->base)
3397                 return skinframe;
3398
3399         skinframe->stain = NULL;
3400         skinframe->merged = NULL;
3401         skinframe->base = NULL;
3402         skinframe->pants = NULL;
3403         skinframe->shirt = NULL;
3404         skinframe->nmap = NULL;
3405         skinframe->gloss = NULL;
3406         skinframe->glow = NULL;
3407         skinframe->fog = NULL;
3408         skinframe->reflect = NULL;
3409         skinframe->hasalpha = false;
3410
3411         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3412         if (!skindata)
3413                 return NULL;
3414
3415         if (developer_loading.integer)
3416                 Con_Printf("loading quake skin \"%s\"\n", name);
3417
3418         // 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)
3419         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3420         memcpy(skinframe->qpixels, skindata, width*height);
3421         skinframe->qwidth = width;
3422         skinframe->qheight = height;
3423
3424         featuresmask = 0;
3425         for (i = 0;i < width * height;i++)
3426                 featuresmask |= palette_featureflags[skindata[i]];
3427
3428         skinframe->hasalpha = false;
3429         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3430         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3431         skinframe->qgeneratemerged = true;
3432         skinframe->qgeneratebase = skinframe->qhascolormapping;
3433         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3434
3435         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3436         //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]);
3437
3438         return skinframe;
3439 }
3440
3441 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3442 {
3443         int width;
3444         int height;
3445         unsigned char *skindata;
3446
3447         if (!skinframe->qpixels)
3448                 return;
3449
3450         if (!skinframe->qhascolormapping)
3451                 colormapped = false;
3452
3453         if (colormapped)
3454         {
3455                 if (!skinframe->qgeneratebase)
3456                         return;
3457         }
3458         else
3459         {
3460                 if (!skinframe->qgeneratemerged)
3461                         return;
3462         }
3463
3464         width = skinframe->qwidth;
3465         height = skinframe->qheight;
3466         skindata = skinframe->qpixels;
3467
3468         if (skinframe->qgeneratenmap)
3469         {
3470                 unsigned char *temp1, *temp2;
3471                 skinframe->qgeneratenmap = false;
3472                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3473                 temp2 = temp1 + width * height * 4;
3474                 // use either a custom palette or the quake palette
3475                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3476                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3477                 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);
3478                 Mem_Free(temp1);
3479         }
3480
3481         if (skinframe->qgenerateglow)
3482         {
3483                 skinframe->qgenerateglow = false;
3484                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3485         }
3486
3487         if (colormapped)
3488         {
3489                 skinframe->qgeneratebase = false;
3490                 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);
3491                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3492                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3493         }
3494         else
3495         {
3496                 skinframe->qgeneratemerged = false;
3497                 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);
3498         }
3499
3500         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3501         {
3502                 Mem_Free(skinframe->qpixels);
3503                 skinframe->qpixels = NULL;
3504         }
3505 }
3506
3507 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)
3508 {
3509         int i;
3510         skinframe_t *skinframe;
3511
3512         if (cls.state == ca_dedicated)
3513                 return NULL;
3514
3515         // if already loaded just return it, otherwise make a new skinframe
3516         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3517         if (skinframe && skinframe->base)
3518                 return skinframe;
3519
3520         skinframe->stain = NULL;
3521         skinframe->merged = NULL;
3522         skinframe->base = NULL;
3523         skinframe->pants = NULL;
3524         skinframe->shirt = NULL;
3525         skinframe->nmap = NULL;
3526         skinframe->gloss = NULL;
3527         skinframe->glow = NULL;
3528         skinframe->fog = NULL;
3529         skinframe->reflect = NULL;
3530         skinframe->hasalpha = false;
3531
3532         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3533         if (!skindata)
3534                 return NULL;
3535
3536         if (developer_loading.integer)
3537                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3538
3539         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3540         if (textureflags & TEXF_ALPHA)
3541         {
3542                 for (i = 0;i < width * height;i++)
3543                 {
3544                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3545                         {
3546                                 skinframe->hasalpha = true;
3547                                 break;
3548                         }
3549                 }
3550                 if (r_loadfog && skinframe->hasalpha)
3551                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3552         }
3553
3554         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3555         //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]);
3556
3557         return skinframe;
3558 }
3559
3560 skinframe_t *R_SkinFrame_LoadMissing(void)
3561 {
3562         skinframe_t *skinframe;
3563
3564         if (cls.state == ca_dedicated)
3565                 return NULL;
3566
3567         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3568         skinframe->stain = NULL;
3569         skinframe->merged = NULL;
3570         skinframe->base = NULL;
3571         skinframe->pants = NULL;
3572         skinframe->shirt = NULL;
3573         skinframe->nmap = NULL;
3574         skinframe->gloss = NULL;
3575         skinframe->glow = NULL;
3576         skinframe->fog = NULL;
3577         skinframe->reflect = NULL;
3578         skinframe->hasalpha = false;
3579
3580         skinframe->avgcolor[0] = rand() / RAND_MAX;
3581         skinframe->avgcolor[1] = rand() / RAND_MAX;
3582         skinframe->avgcolor[2] = rand() / RAND_MAX;
3583         skinframe->avgcolor[3] = 1;
3584
3585         return skinframe;
3586 }
3587
3588 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3589 typedef struct suffixinfo_s
3590 {
3591         const char *suffix;
3592         qboolean flipx, flipy, flipdiagonal;
3593 }
3594 suffixinfo_t;
3595 static suffixinfo_t suffix[3][6] =
3596 {
3597         {
3598                 {"px",   false, false, false},
3599                 {"nx",   false, false, false},
3600                 {"py",   false, false, false},
3601                 {"ny",   false, false, false},
3602                 {"pz",   false, false, false},
3603                 {"nz",   false, false, false}
3604         },
3605         {
3606                 {"posx", false, false, false},
3607                 {"negx", false, false, false},
3608                 {"posy", false, false, false},
3609                 {"negy", false, false, false},
3610                 {"posz", false, false, false},
3611                 {"negz", false, false, false}
3612         },
3613         {
3614                 {"rt",    true, false,  true},
3615                 {"lf",   false,  true,  true},
3616                 {"ft",    true,  true, false},
3617                 {"bk",   false, false, false},
3618                 {"up",    true, false,  true},
3619                 {"dn",    true, false,  true}
3620         }
3621 };
3622
3623 static int componentorder[4] = {0, 1, 2, 3};
3624
3625 rtexture_t *R_LoadCubemap(const char *basename)
3626 {
3627         int i, j, cubemapsize;
3628         unsigned char *cubemappixels, *image_buffer;
3629         rtexture_t *cubemaptexture;
3630         char name[256];
3631         // must start 0 so the first loadimagepixels has no requested width/height
3632         cubemapsize = 0;
3633         cubemappixels = NULL;
3634         cubemaptexture = NULL;
3635         // keep trying different suffix groups (posx, px, rt) until one loads
3636         for (j = 0;j < 3 && !cubemappixels;j++)
3637         {
3638                 // load the 6 images in the suffix group
3639                 for (i = 0;i < 6;i++)
3640                 {
3641                         // generate an image name based on the base and and suffix
3642                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3643                         // load it
3644                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3645                         {
3646                                 // an image loaded, make sure width and height are equal
3647                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3648                                 {
3649                                         // if this is the first image to load successfully, allocate the cubemap memory
3650                                         if (!cubemappixels && image_width >= 1)
3651                                         {
3652                                                 cubemapsize = image_width;
3653                                                 // note this clears to black, so unavailable sides are black
3654                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3655                                         }
3656                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3657                                         if (cubemappixels)
3658                                                 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);
3659                                 }
3660                                 else
3661                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3662                                 // free the image
3663                                 Mem_Free(image_buffer);
3664                         }
3665                 }
3666         }
3667         // if a cubemap loaded, upload it
3668         if (cubemappixels)
3669         {
3670                 if (developer_loading.integer)
3671                         Con_Printf("loading cubemap \"%s\"\n", basename);
3672
3673                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3674                 Mem_Free(cubemappixels);
3675         }
3676         else
3677         {
3678                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3679                 if (developer_loading.integer)
3680                 {
3681                         Con_Printf("(tried tried images ");
3682                         for (j = 0;j < 3;j++)
3683                                 for (i = 0;i < 6;i++)
3684                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3685                         Con_Print(" and was unable to find any of them).\n");
3686                 }
3687         }
3688         return cubemaptexture;
3689 }
3690
3691 rtexture_t *R_GetCubemap(const char *basename)
3692 {
3693         int i;
3694         for (i = 0;i < r_texture_numcubemaps;i++)
3695                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3696                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3697         if (i >= MAX_CUBEMAPS)
3698                 return r_texture_whitecube;
3699         r_texture_numcubemaps++;
3700         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3701         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3702         return r_texture_cubemaps[i].texture;
3703 }
3704
3705 void R_FreeCubemaps(void)
3706 {
3707         int i;
3708         for (i = 0;i < r_texture_numcubemaps;i++)
3709         {
3710                 if (developer_loading.integer)
3711                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3712                 if (r_texture_cubemaps[i].texture)
3713                         R_FreeTexture(r_texture_cubemaps[i].texture);
3714         }
3715         r_texture_numcubemaps = 0;
3716 }
3717
3718 void R_Main_FreeViewCache(void)
3719 {
3720         if (r_refdef.viewcache.entityvisible)
3721                 Mem_Free(r_refdef.viewcache.entityvisible);
3722         if (r_refdef.viewcache.world_pvsbits)
3723                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3724         if (r_refdef.viewcache.world_leafvisible)
3725                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3726         if (r_refdef.viewcache.world_surfacevisible)
3727                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3728         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3729 }
3730
3731 void R_Main_ResizeViewCache(void)
3732 {
3733         int numentities = r_refdef.scene.numentities;
3734         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3735         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3736         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3737         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3738         if (r_refdef.viewcache.maxentities < numentities)
3739         {
3740                 r_refdef.viewcache.maxentities = numentities;
3741                 if (r_refdef.viewcache.entityvisible)
3742                         Mem_Free(r_refdef.viewcache.entityvisible);
3743                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3744         }
3745         if (r_refdef.viewcache.world_numclusters != numclusters)
3746         {
3747                 r_refdef.viewcache.world_numclusters = numclusters;
3748                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3749                 if (r_refdef.viewcache.world_pvsbits)
3750                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3751                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3752         }
3753         if (r_refdef.viewcache.world_numleafs != numleafs)
3754         {
3755                 r_refdef.viewcache.world_numleafs = numleafs;
3756                 if (r_refdef.viewcache.world_leafvisible)
3757                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3758                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3759         }
3760         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3761         {
3762                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3763                 if (r_refdef.viewcache.world_surfacevisible)
3764                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3765                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3766         }
3767 }
3768
3769 extern rtexture_t *loadingscreentexture;
3770 void gl_main_start(void)
3771 {
3772         loadingscreentexture = NULL;
3773         r_texture_blanknormalmap = NULL;
3774         r_texture_white = NULL;
3775         r_texture_grey128 = NULL;
3776         r_texture_black = NULL;
3777         r_texture_whitecube = NULL;
3778         r_texture_normalizationcube = NULL;
3779         r_texture_fogattenuation = NULL;
3780         r_texture_fogheighttexture = NULL;
3781         r_texture_gammaramps = NULL;
3782         r_texture_numcubemaps = 0;
3783
3784         r_loaddds = r_texture_dds_load.integer != 0;
3785         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3786
3787         switch(vid.renderpath)
3788         {
3789         case RENDERPATH_GL20:
3790         case RENDERPATH_D3D9:
3791         case RENDERPATH_D3D10:
3792         case RENDERPATH_D3D11:
3793         case RENDERPATH_SOFT:
3794                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3795                 Cvar_SetValueQuick(&gl_combine, 1);
3796                 Cvar_SetValueQuick(&r_glsl, 1);
3797                 r_loadnormalmap = true;
3798                 r_loadgloss = true;
3799                 r_loadfog = false;
3800                 break;
3801         case RENDERPATH_GL13:
3802                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3803                 Cvar_SetValueQuick(&gl_combine, 1);
3804                 Cvar_SetValueQuick(&r_glsl, 0);
3805                 r_loadnormalmap = false;
3806                 r_loadgloss = false;
3807                 r_loadfog = true;
3808                 break;
3809         case RENDERPATH_GL11:
3810                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3811                 Cvar_SetValueQuick(&gl_combine, 0);
3812                 Cvar_SetValueQuick(&r_glsl, 0);
3813                 r_loadnormalmap = false;
3814                 r_loadgloss = false;
3815                 r_loadfog = true;
3816                 break;
3817         case RENDERPATH_GLES2:
3818                 Cvar_SetValueQuick(&r_textureunits, 1);
3819                 Cvar_SetValueQuick(&gl_combine, 1);
3820                 Cvar_SetValueQuick(&r_glsl, 1);
3821                 r_loadnormalmap = true;
3822                 r_loadgloss = false;
3823                 r_loadfog = false;
3824                 break;
3825         }
3826
3827         R_AnimCache_Free();
3828         R_FrameData_Reset();
3829
3830         r_numqueries = 0;
3831         r_maxqueries = 0;
3832         memset(r_queries, 0, sizeof(r_queries));
3833
3834         r_qwskincache = NULL;
3835         r_qwskincache_size = 0;
3836
3837         // set up r_skinframe loading system for textures
3838         memset(&r_skinframe, 0, sizeof(r_skinframe));
3839         r_skinframe.loadsequence = 1;
3840         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3841
3842         r_main_texturepool = R_AllocTexturePool();
3843         R_BuildBlankTextures();
3844         R_BuildNoTexture();
3845         if (vid.support.arb_texture_cube_map)
3846         {
3847                 R_BuildWhiteCube();
3848                 R_BuildNormalizationCube();
3849         }
3850         r_texture_fogattenuation = NULL;
3851         r_texture_fogheighttexture = NULL;
3852         r_texture_gammaramps = NULL;
3853         //r_texture_fogintensity = NULL;
3854         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3855         memset(&r_waterstate, 0, sizeof(r_waterstate));
3856         r_glsl_permutation = NULL;
3857         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3858         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3859         glslshaderstring = NULL;
3860 #ifdef SUPPORTD3D
3861         r_hlsl_permutation = NULL;
3862         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3863         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3864 #endif
3865         hlslshaderstring = NULL;
3866         memset(&r_svbsp, 0, sizeof (r_svbsp));
3867
3868         r_refdef.fogmasktable_density = 0;
3869 }
3870
3871 void gl_main_shutdown(void)
3872 {
3873         R_AnimCache_Free();
3874         R_FrameData_Reset();
3875
3876         R_Main_FreeViewCache();
3877
3878         switch(vid.renderpath)
3879         {
3880         case RENDERPATH_GL11:
3881         case RENDERPATH_GL13:
3882         case RENDERPATH_GL20:
3883         case RENDERPATH_GLES2:
3884                 if (r_maxqueries)
3885                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3886                 break;
3887         case RENDERPATH_D3D9:
3888                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3889                 break;
3890         case RENDERPATH_D3D10:
3891                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3892                 break;
3893         case RENDERPATH_D3D11:
3894                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3895                 break;
3896         case RENDERPATH_SOFT:
3897                 break;
3898         }
3899
3900         r_numqueries = 0;
3901         r_maxqueries = 0;
3902         memset(r_queries, 0, sizeof(r_queries));
3903
3904         r_qwskincache = NULL;
3905         r_qwskincache_size = 0;
3906
3907         // clear out the r_skinframe state
3908         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3909         memset(&r_skinframe, 0, sizeof(r_skinframe));
3910
3911         if (r_svbsp.nodes)
3912                 Mem_Free(r_svbsp.nodes);
3913         memset(&r_svbsp, 0, sizeof (r_svbsp));
3914         R_FreeTexturePool(&r_main_texturepool);
3915         loadingscreentexture = NULL;
3916         r_texture_blanknormalmap = NULL;
3917         r_texture_white = NULL;
3918         r_texture_grey128 = NULL;
3919         r_texture_black = NULL;
3920         r_texture_whitecube = NULL;
3921         r_texture_normalizationcube = NULL;
3922         r_texture_fogattenuation = NULL;
3923         r_texture_fogheighttexture = NULL;
3924         r_texture_gammaramps = NULL;
3925         r_texture_numcubemaps = 0;
3926         //r_texture_fogintensity = NULL;
3927         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3928         memset(&r_waterstate, 0, sizeof(r_waterstate));
3929         R_GLSL_Restart_f();
3930
3931         r_glsl_permutation = NULL;
3932         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3933         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3934         glslshaderstring = NULL;
3935 #ifdef SUPPORTD3D
3936         r_hlsl_permutation = NULL;
3937         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3938         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3939 #endif
3940         hlslshaderstring = NULL;
3941 }
3942
3943 extern void CL_ParseEntityLump(char *entitystring);
3944 void gl_main_newmap(void)
3945 {
3946         // FIXME: move this code to client
3947         char *entities, entname[MAX_QPATH];
3948         if (r_qwskincache)
3949                 Mem_Free(r_qwskincache);
3950         r_qwskincache = NULL;
3951         r_qwskincache_size = 0;
3952         if (cl.worldmodel)
3953         {
3954                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3955                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3956                 {
3957                         CL_ParseEntityLump(entities);
3958                         Mem_Free(entities);
3959                         return;
3960                 }
3961                 if (cl.worldmodel->brush.entities)
3962                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3963         }
3964         R_Main_FreeViewCache();
3965
3966         R_FrameData_Reset();
3967 }
3968
3969 void GL_Main_Init(void)
3970 {
3971         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3972
3973         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3974         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3975         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3976         if (gamemode == GAME_NEHAHRA)
3977         {
3978                 Cvar_RegisterVariable (&gl_fogenable);
3979                 Cvar_RegisterVariable (&gl_fogdensity);
3980                 Cvar_RegisterVariable (&gl_fogred);
3981                 Cvar_RegisterVariable (&gl_foggreen);
3982                 Cvar_RegisterVariable (&gl_fogblue);
3983                 Cvar_RegisterVariable (&gl_fogstart);
3984                 Cvar_RegisterVariable (&gl_fogend);
3985                 Cvar_RegisterVariable (&gl_skyclip);
3986         }
3987         Cvar_RegisterVariable(&r_motionblur);
3988         Cvar_RegisterVariable(&r_motionblur_maxblur);
3989         Cvar_RegisterVariable(&r_motionblur_bmin);
3990         Cvar_RegisterVariable(&r_motionblur_vmin);
3991         Cvar_RegisterVariable(&r_motionblur_vmax);
3992         Cvar_RegisterVariable(&r_motionblur_vcoeff);
3993         Cvar_RegisterVariable(&r_motionblur_randomize);
3994         Cvar_RegisterVariable(&r_damageblur);
3995         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3996         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3997         Cvar_RegisterVariable(&r_equalize_entities_by);
3998         Cvar_RegisterVariable(&r_equalize_entities_to);
3999         Cvar_RegisterVariable(&r_depthfirst);
4000         Cvar_RegisterVariable(&r_useinfinitefarclip);
4001         Cvar_RegisterVariable(&r_farclip_base);
4002         Cvar_RegisterVariable(&r_farclip_world);
4003         Cvar_RegisterVariable(&r_nearclip);
4004         Cvar_RegisterVariable(&r_showbboxes);
4005         Cvar_RegisterVariable(&r_showsurfaces);
4006         Cvar_RegisterVariable(&r_showtris);
4007         Cvar_RegisterVariable(&r_shownormals);
4008         Cvar_RegisterVariable(&r_showlighting);
4009         Cvar_RegisterVariable(&r_showshadowvolumes);
4010         Cvar_RegisterVariable(&r_showcollisionbrushes);
4011         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4012         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4013         Cvar_RegisterVariable(&r_showdisabledepthtest);
4014         Cvar_RegisterVariable(&r_drawportals);
4015         Cvar_RegisterVariable(&r_drawentities);
4016         Cvar_RegisterVariable(&r_draw2d);
4017         Cvar_RegisterVariable(&r_drawworld);
4018         Cvar_RegisterVariable(&r_cullentities_trace);
4019         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4020         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4021         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4022         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4023         Cvar_RegisterVariable(&r_drawviewmodel);
4024         Cvar_RegisterVariable(&r_drawexteriormodel);
4025         Cvar_RegisterVariable(&r_speeds);
4026         Cvar_RegisterVariable(&r_fullbrights);
4027         Cvar_RegisterVariable(&r_wateralpha);
4028         Cvar_RegisterVariable(&r_dynamic);
4029         Cvar_RegisterVariable(&r_fakelight);
4030         Cvar_RegisterVariable(&r_fakelight_intensity);
4031         Cvar_RegisterVariable(&r_fullbright);
4032         Cvar_RegisterVariable(&r_shadows);
4033         Cvar_RegisterVariable(&r_shadows_darken);
4034         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4035         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4036         Cvar_RegisterVariable(&r_shadows_throwdistance);
4037         Cvar_RegisterVariable(&r_shadows_throwdirection);
4038         Cvar_RegisterVariable(&r_shadows_focus);
4039         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4040         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4041         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4042         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4043         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4044         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4045         Cvar_RegisterVariable(&r_fog_exp2);
4046         Cvar_RegisterVariable(&r_drawfog);
4047         Cvar_RegisterVariable(&r_transparentdepthmasking);
4048         Cvar_RegisterVariable(&r_texture_dds_load);
4049         Cvar_RegisterVariable(&r_texture_dds_save);
4050         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4051         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4052         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4053         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4054         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4055         Cvar_RegisterVariable(&r_textureunits);
4056         Cvar_RegisterVariable(&gl_combine);
4057         Cvar_RegisterVariable(&r_glsl);
4058         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4059         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4060         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4061         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4062         Cvar_RegisterVariable(&r_glsl_postprocess);
4063         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4064         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4065         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4066         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4067         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4068         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4069         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4070         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4071
4072         Cvar_RegisterVariable(&r_water);
4073         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4074         Cvar_RegisterVariable(&r_water_clippingplanebias);
4075         Cvar_RegisterVariable(&r_water_refractdistort);
4076         Cvar_RegisterVariable(&r_water_reflectdistort);
4077         Cvar_RegisterVariable(&r_water_scissormode);
4078         Cvar_RegisterVariable(&r_lerpsprites);
4079         Cvar_RegisterVariable(&r_lerpmodels);
4080         Cvar_RegisterVariable(&r_lerplightstyles);
4081         Cvar_RegisterVariable(&r_waterscroll);
4082         Cvar_RegisterVariable(&r_bloom);
4083         Cvar_RegisterVariable(&r_bloom_colorscale);
4084         Cvar_RegisterVariable(&r_bloom_brighten);
4085         Cvar_RegisterVariable(&r_bloom_blur);
4086         Cvar_RegisterVariable(&r_bloom_resolution);
4087         Cvar_RegisterVariable(&r_bloom_colorexponent);
4088         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4089         Cvar_RegisterVariable(&r_hdr);
4090         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4091         Cvar_RegisterVariable(&r_hdr_glowintensity);
4092         Cvar_RegisterVariable(&r_hdr_range);
4093         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4094         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4095         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4096         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4097         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4098         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4099         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4100         Cvar_RegisterVariable(&developer_texturelogging);
4101         Cvar_RegisterVariable(&gl_lightmaps);
4102         Cvar_RegisterVariable(&r_test);
4103         Cvar_RegisterVariable(&r_glsl_saturation);
4104         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4105         Cvar_RegisterVariable(&r_framedatasize);
4106         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4107                 Cvar_SetValue("r_fullbrights", 0);
4108         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4109
4110         Cvar_RegisterVariable(&r_track_sprites);
4111         Cvar_RegisterVariable(&r_track_sprites_flags);
4112         Cvar_RegisterVariable(&r_track_sprites_scalew);
4113         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4114         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4115         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4116         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4117         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4118 }
4119
4120 extern void R_Textures_Init(void);
4121 extern void GL_Draw_Init(void);
4122 extern void GL_Main_Init(void);
4123 extern void R_Shadow_Init(void);
4124 extern void R_Sky_Init(void);
4125 extern void GL_Surf_Init(void);
4126 extern void R_Particles_Init(void);
4127 extern void R_Explosion_Init(void);
4128 extern void gl_backend_init(void);
4129 extern void Sbar_Init(void);
4130 extern void R_LightningBeams_Init(void);
4131 extern void Mod_RenderInit(void);
4132 extern void Font_Init(void);
4133
4134 void Render_Init(void)
4135 {
4136         gl_backend_init();
4137         R_Textures_Init();
4138         GL_Main_Init();
4139         Font_Init();
4140         GL_Draw_Init();
4141         R_Shadow_Init();
4142         R_Sky_Init();
4143         GL_Surf_Init();
4144         Sbar_Init();
4145         R_Particles_Init();
4146         R_Explosion_Init();
4147         R_LightningBeams_Init();
4148         Mod_RenderInit();
4149 }
4150
4151 /*
4152 ===============
4153 GL_Init
4154 ===============
4155 */
4156 extern char *ENGINE_EXTENSIONS;
4157 void GL_Init (void)
4158 {
4159         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4160         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4161         gl_version = (const char *)qglGetString(GL_VERSION);
4162         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4163
4164         if (!gl_extensions)
4165                 gl_extensions = "";
4166         if (!gl_platformextensions)
4167                 gl_platformextensions = "";
4168
4169         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4170         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4171         Con_Printf("GL_VERSION: %s\n", gl_version);
4172         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4173         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4174
4175         VID_CheckExtensions();
4176
4177         // LordHavoc: report supported extensions
4178         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4179
4180         // clear to black (loading plaque will be seen over this)
4181         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4182 }
4183
4184 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4185 {
4186         int i;
4187         mplane_t *p;
4188         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4189         {
4190                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4191                 if (i == 4)
4192                         continue;
4193                 p = r_refdef.view.frustum + i;
4194                 switch(p->signbits)
4195                 {
4196                 default:
4197                 case 0:
4198                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4199                                 return true;
4200                         break;
4201                 case 1:
4202                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4203                                 return true;
4204                         break;
4205                 case 2:
4206                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4207                                 return true;
4208                         break;
4209                 case 3:
4210                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4211                                 return true;
4212                         break;
4213                 case 4:
4214                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4215                                 return true;
4216                         break;
4217                 case 5:
4218                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4219                                 return true;
4220                         break;
4221                 case 6:
4222                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4223                                 return true;
4224                         break;
4225                 case 7:
4226                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4227                                 return true;
4228                         break;
4229                 }
4230         }
4231         return false;
4232 }
4233
4234 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4235 {
4236         int i;
4237         const mplane_t *p;
4238         for (i = 0;i < numplanes;i++)
4239         {
4240                 p = planes + i;
4241                 switch(p->signbits)
4242                 {
4243                 default:
4244                 case 0:
4245                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4246                                 return true;
4247                         break;
4248                 case 1:
4249                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4250                                 return true;
4251                         break;
4252                 case 2:
4253                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4254                                 return true;
4255                         break;
4256                 case 3:
4257                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 4:
4261                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 5:
4265                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 case 6:
4269                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4270                                 return true;
4271                         break;
4272                 case 7:
4273                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4274                                 return true;
4275                         break;
4276                 }
4277         }
4278         return false;
4279 }
4280
4281 //==================================================================================
4282
4283 // LordHavoc: this stores temporary data used within the same frame
4284
4285 typedef struct r_framedata_mem_s
4286 {
4287         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4288         size_t size; // how much usable space
4289         size_t current; // how much space in use
4290         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4291         size_t wantedsize; // how much space was allocated
4292         unsigned char *data; // start of real data (16byte aligned)
4293 }
4294 r_framedata_mem_t;
4295
4296 static r_framedata_mem_t *r_framedata_mem;
4297
4298 void R_FrameData_Reset(void)
4299 {
4300         while (r_framedata_mem)
4301         {
4302                 r_framedata_mem_t *next = r_framedata_mem->purge;
4303                 Mem_Free(r_framedata_mem);
4304                 r_framedata_mem = next;
4305         }
4306 }
4307
4308 void R_FrameData_Resize(void)
4309 {
4310         size_t wantedsize;
4311         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4312         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4313         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4314         {
4315                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4316                 newmem->wantedsize = wantedsize;
4317                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4318                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4319                 newmem->current = 0;
4320                 newmem->mark = 0;
4321                 newmem->purge = r_framedata_mem;
4322                 r_framedata_mem = newmem;
4323         }
4324 }
4325
4326 void R_FrameData_NewFrame(void)
4327 {
4328         R_FrameData_Resize();
4329         if (!r_framedata_mem)
4330                 return;
4331         // if we ran out of space on the last frame, free the old memory now
4332         while (r_framedata_mem->purge)
4333         {
4334                 // repeatedly remove the second item in the list, leaving only head
4335                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4336                 Mem_Free(r_framedata_mem->purge);
4337                 r_framedata_mem->purge = next;
4338         }
4339         // reset the current mem pointer
4340         r_framedata_mem->current = 0;
4341         r_framedata_mem->mark = 0;
4342 }
4343
4344 void *R_FrameData_Alloc(size_t size)
4345 {
4346         void *data;
4347
4348         // align to 16 byte boundary - the data pointer is already aligned, so we
4349         // only need to ensure the size of every allocation is also aligned
4350         size = (size + 15) & ~15;
4351
4352         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4353         {
4354                 // emergency - we ran out of space, allocate more memory
4355                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4356                 R_FrameData_Resize();
4357         }
4358
4359         data = r_framedata_mem->data + r_framedata_mem->current;
4360         r_framedata_mem->current += size;
4361
4362         // count the usage for stats
4363         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4364         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4365
4366         return (void *)data;
4367 }
4368
4369 void *R_FrameData_Store(size_t size, void *data)
4370 {
4371         void *d = R_FrameData_Alloc(size);
4372         if (d && data)
4373                 memcpy(d, data, size);
4374         return d;
4375 }
4376
4377 void R_FrameData_SetMark(void)
4378 {
4379         if (!r_framedata_mem)
4380                 return;
4381         r_framedata_mem->mark = r_framedata_mem->current;
4382 }
4383
4384 void R_FrameData_ReturnToMark(void)
4385 {
4386         if (!r_framedata_mem)
4387                 return;
4388         r_framedata_mem->current = r_framedata_mem->mark;
4389 }
4390
4391 //==================================================================================
4392
4393 // LordHavoc: animcache originally written by Echon, rewritten since then
4394
4395 /**
4396  * Animation cache prevents re-generating mesh data for an animated model
4397  * multiple times in one frame for lighting, shadowing, reflections, etc.
4398  */
4399
4400 void R_AnimCache_Free(void)
4401 {
4402 }
4403
4404 void R_AnimCache_ClearCache(void)
4405 {
4406         int i;
4407         entity_render_t *ent;
4408
4409         for (i = 0;i < r_refdef.scene.numentities;i++)
4410         {
4411                 ent = r_refdef.scene.entities[i];
4412                 ent->animcache_vertex3f = NULL;
4413                 ent->animcache_normal3f = NULL;
4414                 ent->animcache_svector3f = NULL;
4415                 ent->animcache_tvector3f = NULL;
4416                 ent->animcache_vertexmesh = NULL;
4417                 ent->animcache_vertex3fbuffer = NULL;
4418                 ent->animcache_vertexmeshbuffer = NULL;
4419         }
4420 }
4421
4422 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4423 {
4424         int i;
4425
4426         // check if we need the meshbuffers
4427         if (!vid.useinterleavedarrays)
4428                 return;
4429
4430         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4431                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4432         // TODO: upload vertex3f buffer?
4433         if (ent->animcache_vertexmesh)
4434         {
4435                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4436                 for (i = 0;i < numvertices;i++)
4437                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4438                 if (ent->animcache_svector3f)
4439                         for (i = 0;i < numvertices;i++)
4440                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4441                 if (ent->animcache_tvector3f)
4442                         for (i = 0;i < numvertices;i++)
4443                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4444                 if (ent->animcache_normal3f)
4445                         for (i = 0;i < numvertices;i++)
4446                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4447                 // TODO: upload vertexmeshbuffer?
4448         }
4449 }
4450
4451 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4452 {
4453         dp_model_t *model = ent->model;
4454         int numvertices;
4455         // see if it's already cached this frame
4456         if (ent->animcache_vertex3f)
4457         {
4458                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4459                 if (wantnormals || wanttangents)
4460                 {
4461                         if (ent->animcache_normal3f)
4462                                 wantnormals = false;
4463                         if (ent->animcache_svector3f)
4464                                 wanttangents = false;
4465                         if (wantnormals || wanttangents)
4466                         {
4467                                 numvertices = model->surfmesh.num_vertices;
4468                                 if (wantnormals)
4469                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4470                                 if (wanttangents)
4471                                 {
4472                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4473                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4474                                 }
4475                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4476                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4477                         }
4478                 }
4479         }
4480         else
4481         {
4482                 // see if this ent is worth caching
4483                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4484                         return false;
4485                 // get some memory for this entity and generate mesh data
4486                 numvertices = model->surfmesh.num_vertices;
4487                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4488                 if (wantnormals)
4489                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4490                 if (wanttangents)
4491                 {
4492                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4493                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4494                 }
4495                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4496                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4497         }
4498         return true;
4499 }
4500
4501 void R_AnimCache_CacheVisibleEntities(void)
4502 {
4503         int i;
4504         qboolean wantnormals = true;
4505         qboolean wanttangents = !r_showsurfaces.integer;
4506
4507         switch(vid.renderpath)
4508         {
4509         case RENDERPATH_GL20:
4510         case RENDERPATH_D3D9:
4511         case RENDERPATH_D3D10:
4512         case RENDERPATH_D3D11:
4513         case RENDERPATH_GLES2:
4514                 break;
4515         case RENDERPATH_GL13:
4516         case RENDERPATH_GL11:
4517                 wanttangents = false;
4518                 break;
4519         case RENDERPATH_SOFT:
4520                 break;
4521         }
4522
4523         if (r_shownormals.integer)
4524                 wanttangents = wantnormals = true;
4525
4526         // TODO: thread this
4527         // NOTE: R_PrepareRTLights() also caches entities
4528
4529         for (i = 0;i < r_refdef.scene.numentities;i++)
4530                 if (r_refdef.viewcache.entityvisible[i])
4531                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4532 }
4533
4534 //==================================================================================
4535
4536 static void R_View_UpdateEntityLighting (void)
4537 {
4538         int i;
4539         entity_render_t *ent;
4540         vec3_t tempdiffusenormal, avg;
4541         vec_t f, fa, fd, fdd;
4542         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4543
4544         for (i = 0;i < r_refdef.scene.numentities;i++)
4545         {
4546                 ent = r_refdef.scene.entities[i];
4547
4548                 // skip unseen models
4549                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4550                         continue;
4551
4552                 // skip bsp models
4553                 if (ent->model && ent->model->brush.num_leafs)
4554                 {
4555                         // TODO: use modellight for r_ambient settings on world?
4556                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4557                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4558                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4559                         continue;
4560                 }
4561
4562                 // fetch the lighting from the worldmodel data
4563                 VectorClear(ent->modellight_ambient);
4564                 VectorClear(ent->modellight_diffuse);
4565                 VectorClear(tempdiffusenormal);
4566                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4567                 {
4568                         vec3_t org;
4569                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4570
4571                         // complete lightning for lit sprites
4572                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4573                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4574                         {
4575                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4576                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4577                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4578                         }
4579                         else
4580                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4581
4582                         if(ent->flags & RENDER_EQUALIZE)
4583                         {
4584                                 // first fix up ambient lighting...
4585                                 if(r_equalize_entities_minambient.value > 0)
4586                                 {
4587                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4588                                         if(fd > 0)
4589                                         {
4590                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4591                                                 if(fa < r_equalize_entities_minambient.value * fd)
4592                                                 {
4593                                                         // solve:
4594                                                         //   fa'/fd' = minambient
4595                                                         //   fa'+0.25*fd' = fa+0.25*fd
4596                                                         //   ...
4597                                                         //   fa' = fd' * minambient
4598                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4599                                                         //   ...
4600                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4601                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4602                                                         //   ...
4603                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4604                                                         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
4605                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4606                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4607                                                 }
4608                                         }
4609                                 }
4610
4611                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4612                                 {
4613                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4614                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4615                                         f = fa + 0.25 * fd;
4616                                         if(f > 0)
4617                                         {
4618                                                 // adjust brightness and saturation to target
4619                                                 avg[0] = avg[1] = avg[2] = fa / f;
4620                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4621                                                 avg[0] = avg[1] = avg[2] = fd / f;
4622                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4623                                         }
4624                                 }
4625                         }
4626                 }
4627                 else // highly rare
4628                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4629
4630                 // move the light direction into modelspace coordinates for lighting code
4631                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4632                 if(VectorLength2(ent->modellight_lightdir) == 0)
4633                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4634                 VectorNormalize(ent->modellight_lightdir);
4635         }
4636 }
4637
4638 #define MAX_LINEOFSIGHTTRACES 64
4639
4640 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4641 {
4642         int i;
4643         vec3_t boxmins, boxmaxs;
4644         vec3_t start;
4645         vec3_t end;
4646         dp_model_t *model = r_refdef.scene.worldmodel;
4647
4648         if (!model || !model->brush.TraceLineOfSight)
4649                 return true;
4650
4651         // expand the box a little
4652         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4653         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4654         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4655         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4656         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4657         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4658
4659         // return true if eye is inside enlarged box
4660         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4661                 return true;
4662
4663         // try center
4664         VectorCopy(eye, start);
4665         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4666         if (model->brush.TraceLineOfSight(model, start, end))
4667                 return true;
4668
4669         // try various random positions
4670         for (i = 0;i < numsamples;i++)
4671         {
4672                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4673                 if (model->brush.TraceLineOfSight(model, start, end))
4674                         return true;
4675         }
4676
4677         return false;
4678 }
4679
4680
4681 static void R_View_UpdateEntityVisible (void)
4682 {
4683         int i;
4684         int renderimask;
4685         int samples;
4686         entity_render_t *ent;
4687
4688         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4689                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4690                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4691                 :                                                          RENDER_EXTERIORMODEL;
4692         if (!r_drawviewmodel.integer)
4693                 renderimask |= RENDER_VIEWMODEL;
4694         if (!r_drawexteriormodel.integer)
4695                 renderimask |= RENDER_EXTERIORMODEL;
4696         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4697         {
4698                 // worldmodel can check visibility
4699                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4700                 for (i = 0;i < r_refdef.scene.numentities;i++)
4701                 {
4702                         ent = r_refdef.scene.entities[i];
4703                         if (!(ent->flags & renderimask))
4704                         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)))
4705                         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))
4706                                 r_refdef.viewcache.entityvisible[i] = true;
4707                 }
4708                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4709                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4710                 {
4711                         for (i = 0;i < r_refdef.scene.numentities;i++)
4712                         {
4713                                 ent = r_refdef.scene.entities[i];
4714                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4715                                 {
4716                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4717                                         if (samples < 0)
4718                                                 continue; // temp entities do pvs only
4719                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4720                                                 ent->last_trace_visibility = realtime;
4721                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4722                                                 r_refdef.viewcache.entityvisible[i] = 0;
4723                                 }
4724                         }
4725                 }
4726         }
4727         else
4728         {
4729                 // no worldmodel or it can't check visibility
4730                 for (i = 0;i < r_refdef.scene.numentities;i++)
4731                 {
4732                         ent = r_refdef.scene.entities[i];
4733                         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));
4734                 }
4735         }
4736 }
4737
4738 /// only used if skyrendermasked, and normally returns false
4739 int R_DrawBrushModelsSky (void)
4740 {
4741         int i, sky;
4742         entity_render_t *ent;
4743
4744         sky = false;
4745         for (i = 0;i < r_refdef.scene.numentities;i++)
4746         {
4747                 if (!r_refdef.viewcache.entityvisible[i])
4748                         continue;
4749                 ent = r_refdef.scene.entities[i];
4750                 if (!ent->model || !ent->model->DrawSky)
4751                         continue;
4752                 ent->model->DrawSky(ent);
4753                 sky = true;
4754         }
4755         return sky;
4756 }
4757
4758 static void R_DrawNoModel(entity_render_t *ent);
4759 static void R_DrawModels(void)
4760 {
4761         int i;
4762         entity_render_t *ent;
4763
4764         for (i = 0;i < r_refdef.scene.numentities;i++)
4765         {
4766                 if (!r_refdef.viewcache.entityvisible[i])
4767                         continue;
4768                 ent = r_refdef.scene.entities[i];
4769                 r_refdef.stats.entities++;
4770                 if (ent->model && ent->model->Draw != NULL)
4771                         ent->model->Draw(ent);
4772                 else
4773                         R_DrawNoModel(ent);
4774         }
4775 }
4776
4777 static void R_DrawModelsDepth(void)
4778 {
4779         int i;
4780         entity_render_t *ent;
4781
4782         for (i = 0;i < r_refdef.scene.numentities;i++)
4783         {
4784                 if (!r_refdef.viewcache.entityvisible[i])
4785                         continue;
4786                 ent = r_refdef.scene.entities[i];
4787                 if (ent->model && ent->model->DrawDepth != NULL)
4788                         ent->model->DrawDepth(ent);
4789         }
4790 }
4791
4792 static void R_DrawModelsDebug(void)
4793 {
4794         int i;
4795         entity_render_t *ent;
4796
4797         for (i = 0;i < r_refdef.scene.numentities;i++)
4798         {
4799                 if (!r_refdef.viewcache.entityvisible[i])
4800                         continue;
4801                 ent = r_refdef.scene.entities[i];
4802                 if (ent->model && ent->model->DrawDebug != NULL)
4803                         ent->model->DrawDebug(ent);
4804         }
4805 }
4806
4807 static void R_DrawModelsAddWaterPlanes(void)
4808 {
4809         int i;
4810         entity_render_t *ent;
4811
4812         for (i = 0;i < r_refdef.scene.numentities;i++)
4813         {
4814                 if (!r_refdef.viewcache.entityvisible[i])
4815                         continue;
4816                 ent = r_refdef.scene.entities[i];
4817                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4818                         ent->model->DrawAddWaterPlanes(ent);
4819         }
4820 }
4821
4822 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4823 {
4824         if (r_hdr_irisadaptation.integer)
4825         {
4826                 vec3_t ambient;
4827                 vec3_t diffuse;
4828                 vec3_t diffusenormal;
4829                 vec_t brightness;
4830                 vec_t goal;
4831                 vec_t adjust;
4832                 vec_t current;
4833                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4834                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4835                 brightness = max(0.0000001f, brightness);
4836                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4837                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4838                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4839                 current = r_hdr_irisadaptation_value.value;
4840                 if (current < goal)
4841                         current = min(current + adjust, goal);
4842                 else if (current > goal)
4843                         current = max(current - adjust, goal);
4844                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4845                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4846         }
4847         else if (r_hdr_irisadaptation_value.value != 1.0f)
4848                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4849 }
4850
4851 static void R_View_SetFrustum(const int *scissor)
4852 {
4853         int i;
4854         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4855         vec3_t forward, left, up, origin, v;
4856
4857         if(scissor)
4858         {
4859                 // flipped x coordinates (because x points left here)
4860                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4861                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4862
4863                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4864                 switch(vid.renderpath)
4865                 {
4866                         case RENDERPATH_D3D9:
4867                         case RENDERPATH_D3D10:
4868                         case RENDERPATH_D3D11:
4869                         case RENDERPATH_SOFT:
4870                                 // non-flipped y coordinates
4871                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4872                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4873                                 break;
4874                         case RENDERPATH_GL11:
4875                         case RENDERPATH_GL13:
4876                         case RENDERPATH_GL20:
4877                         case RENDERPATH_GLES2:
4878                                 // non-flipped y coordinates
4879                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4880                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4881                                 break;
4882                 }
4883         }
4884
4885         // we can't trust r_refdef.view.forward and friends in reflected scenes
4886         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4887
4888 #if 0
4889         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4890         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4891         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4892         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4893         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4894         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4895         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4896         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4897         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4898         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4899         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4900         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4901 #endif
4902
4903 #if 0
4904         zNear = r_refdef.nearclip;
4905         nudge = 1.0 - 1.0 / (1<<23);
4906         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4907         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4908         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4909         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4910         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4911         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4912         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4913         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4914 #endif
4915
4916
4917
4918 #if 0
4919         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4920         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4921         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4922         r_refdef.view.frustum[0].dist = m[15] - m[12];
4923
4924         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4925         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4926         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4927         r_refdef.view.frustum[1].dist = m[15] + m[12];
4928
4929         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4930         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4931         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4932         r_refdef.view.frustum[2].dist = m[15] - m[13];
4933
4934         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4935         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4936         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4937         r_refdef.view.frustum[3].dist = m[15] + m[13];
4938
4939         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4940         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4941         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4942         r_refdef.view.frustum[4].dist = m[15] - m[14];
4943
4944         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4945         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4946         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4947         r_refdef.view.frustum[5].dist = m[15] + m[14];
4948 #endif
4949
4950         if (r_refdef.view.useperspective)
4951         {
4952                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4953                 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]);
4954                 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]);
4955                 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]);
4956                 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]);
4957
4958                 // then the normals from the corners relative to origin
4959                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4960                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4961                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4962                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4963
4964                 // in a NORMAL view, forward cross left == up
4965                 // in a REFLECTED view, forward cross left == down
4966                 // so our cross products above need to be adjusted for a left handed coordinate system
4967                 CrossProduct(forward, left, v);
4968                 if(DotProduct(v, up) < 0)
4969                 {
4970                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4971                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4972                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4973                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4974                 }
4975
4976                 // Leaving those out was a mistake, those were in the old code, and they
4977                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4978                 // I couldn't reproduce it after adding those normalizations. --blub
4979                 VectorNormalize(r_refdef.view.frustum[0].normal);
4980                 VectorNormalize(r_refdef.view.frustum[1].normal);
4981                 VectorNormalize(r_refdef.view.frustum[2].normal);
4982                 VectorNormalize(r_refdef.view.frustum[3].normal);
4983
4984                 // make the corners absolute
4985                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4986                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4987                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4988                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4989
4990                 // one more normal
4991                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
4992
4993                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
4994                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
4995                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
4996                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
4997                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
4998         }
4999         else
5000         {
5001                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5002                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5003                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5004                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5005                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5006                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5007                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5008                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5009                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5010                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5011         }
5012         r_refdef.view.numfrustumplanes = 5;
5013
5014         if (r_refdef.view.useclipplane)
5015         {
5016                 r_refdef.view.numfrustumplanes = 6;
5017                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5018         }
5019
5020         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5021                 PlaneClassify(r_refdef.view.frustum + i);
5022
5023         // LordHavoc: note to all quake engine coders, Quake had a special case
5024         // for 90 degrees which assumed a square view (wrong), so I removed it,
5025         // Quake2 has it disabled as well.
5026
5027         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5028         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5029         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5030         //PlaneClassify(&frustum[0]);
5031
5032         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5033         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5034         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5035         //PlaneClassify(&frustum[1]);
5036
5037         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5038         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5039         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5040         //PlaneClassify(&frustum[2]);
5041
5042         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5043         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5044         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5045         //PlaneClassify(&frustum[3]);
5046
5047         // nearclip plane
5048         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5049         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5050         //PlaneClassify(&frustum[4]);
5051 }
5052
5053 void R_View_UpdateWithScissor(const int *myscissor)
5054 {
5055         R_Main_ResizeViewCache();
5056         R_View_SetFrustum(myscissor);
5057         R_View_WorldVisibility(r_refdef.view.useclipplane);
5058         R_View_UpdateEntityVisible();
5059         R_View_UpdateEntityLighting();
5060 }
5061
5062 void R_View_Update(void)
5063 {
5064         R_Main_ResizeViewCache();
5065         R_View_SetFrustum(NULL);
5066         R_View_WorldVisibility(r_refdef.view.useclipplane);
5067         R_View_UpdateEntityVisible();
5068         R_View_UpdateEntityLighting();
5069 }
5070
5071 void R_SetupView(qboolean allowwaterclippingplane)
5072 {
5073         const float *customclipplane = NULL;
5074         float plane[4];
5075         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5076         {
5077                 // LordHavoc: couldn't figure out how to make this approach the
5078                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5079                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5080                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5081                         dist = r_refdef.view.clipplane.dist;
5082                 plane[0] = r_refdef.view.clipplane.normal[0];
5083                 plane[1] = r_refdef.view.clipplane.normal[1];
5084                 plane[2] = r_refdef.view.clipplane.normal[2];
5085                 plane[3] = dist;
5086                 customclipplane = plane;
5087         }
5088
5089         if (!r_refdef.view.useperspective)
5090                 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);
5091         else if (vid.stencil && r_useinfinitefarclip.integer)
5092                 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);
5093         else
5094                 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);
5095         R_SetViewport(&r_refdef.view.viewport);
5096 }
5097
5098 void R_EntityMatrix(const matrix4x4_t *matrix)
5099 {
5100         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5101         {
5102                 gl_modelmatrixchanged = false;
5103                 gl_modelmatrix = *matrix;
5104                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5105                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5106                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5107                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5108                 CHECKGLERROR
5109                 switch(vid.renderpath)
5110                 {
5111                 case RENDERPATH_D3D9:
5112 #ifdef SUPPORTD3D
5113                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5114                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5115 #endif
5116                         break;
5117                 case RENDERPATH_D3D10:
5118                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5119                         break;
5120                 case RENDERPATH_D3D11:
5121                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5122                         break;
5123                 case RENDERPATH_GL13:
5124                 case RENDERPATH_GL11:
5125                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5126                         break;
5127                 case RENDERPATH_SOFT:
5128                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5129                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5130                         break;
5131                 case RENDERPATH_GL20:
5132                 case RENDERPATH_GLES2:
5133                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5134                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5135                         break;
5136                 }
5137         }
5138 }
5139
5140 void R_ResetViewRendering2D(void)
5141 {
5142         r_viewport_t viewport;
5143         DrawQ_Finish();
5144
5145         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5146         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);
5147         R_SetViewport(&viewport);
5148         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5149         GL_Color(1, 1, 1, 1);
5150         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5151         GL_BlendFunc(GL_ONE, GL_ZERO);
5152         GL_ScissorTest(false);
5153         GL_DepthMask(false);
5154         GL_DepthRange(0, 1);
5155         GL_DepthTest(false);
5156         GL_DepthFunc(GL_LEQUAL);
5157         R_EntityMatrix(&identitymatrix);
5158         R_Mesh_ResetTextureState();
5159         GL_PolygonOffset(0, 0);
5160         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5161         switch(vid.renderpath)
5162         {
5163         case RENDERPATH_GL11:
5164         case RENDERPATH_GL13:
5165         case RENDERPATH_GL20:
5166         case RENDERPATH_GLES2:
5167                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5168                 break;
5169         case RENDERPATH_D3D9:
5170         case RENDERPATH_D3D10:
5171         case RENDERPATH_D3D11:
5172         case RENDERPATH_SOFT:
5173                 break;
5174         }
5175         GL_CullFace(GL_NONE);
5176 }
5177
5178 void R_ResetViewRendering3D(void)
5179 {
5180         DrawQ_Finish();
5181
5182         R_SetupView(true);
5183         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5184         GL_Color(1, 1, 1, 1);
5185         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5186         GL_BlendFunc(GL_ONE, GL_ZERO);
5187         GL_ScissorTest(true);
5188         GL_DepthMask(true);
5189         GL_DepthRange(0, 1);
5190         GL_DepthTest(true);
5191         GL_DepthFunc(GL_LEQUAL);
5192         R_EntityMatrix(&identitymatrix);
5193         R_Mesh_ResetTextureState();
5194         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5195         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5196         switch(vid.renderpath)
5197         {
5198         case RENDERPATH_GL11:
5199         case RENDERPATH_GL13:
5200         case RENDERPATH_GL20:
5201         case RENDERPATH_GLES2:
5202                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5203                 break;
5204         case RENDERPATH_D3D9:
5205         case RENDERPATH_D3D10:
5206         case RENDERPATH_D3D11:
5207         case RENDERPATH_SOFT:
5208                 break;
5209         }
5210         GL_CullFace(r_refdef.view.cullface_back);
5211 }
5212
5213 /*
5214 ================
5215 R_RenderView_UpdateViewVectors
5216 ================
5217 */
5218 static void R_RenderView_UpdateViewVectors(void)
5219 {
5220         // break apart the view matrix into vectors for various purposes
5221         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5222         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5223         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5224         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5225         // make an inverted copy of the view matrix for tracking sprites
5226         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5227 }
5228
5229 void R_RenderScene(void);
5230 void R_RenderWaterPlanes(void);
5231
5232 static void R_Water_StartFrame(void)
5233 {
5234         int i;
5235         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5236         r_waterstate_waterplane_t *p;
5237
5238         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5239                 return;
5240
5241         switch(vid.renderpath)
5242         {
5243         case RENDERPATH_GL20:
5244         case RENDERPATH_D3D9:
5245         case RENDERPATH_D3D10:
5246         case RENDERPATH_D3D11:
5247         case RENDERPATH_SOFT:
5248         case RENDERPATH_GLES2:
5249                 break;
5250         case RENDERPATH_GL13:
5251         case RENDERPATH_GL11:
5252                 return;
5253         }
5254
5255         // set waterwidth and waterheight to the water resolution that will be
5256         // used (often less than the screen resolution for faster rendering)
5257         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5258         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5259
5260         // calculate desired texture sizes
5261         // can't use water if the card does not support the texture size
5262         if (!r_water.integer || r_showsurfaces.integer)
5263                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5264         else if (vid.support.arb_texture_non_power_of_two)
5265         {
5266                 texturewidth = waterwidth;
5267                 textureheight = waterheight;
5268                 camerawidth = waterwidth;
5269                 cameraheight = waterheight;
5270         }
5271         else
5272         {
5273                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5274                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5275                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5276                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5277         }
5278
5279         // allocate textures as needed
5280         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5281         {
5282                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5283                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5284                 {
5285                         if (p->texture_refraction)
5286                                 R_FreeTexture(p->texture_refraction);
5287                         p->texture_refraction = NULL;
5288                         if (p->texture_reflection)
5289                                 R_FreeTexture(p->texture_reflection);
5290                         p->texture_reflection = NULL;
5291                         if (p->texture_camera)
5292                                 R_FreeTexture(p->texture_camera);
5293                         p->texture_camera = NULL;
5294                 }
5295                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5296                 r_waterstate.texturewidth = texturewidth;
5297                 r_waterstate.textureheight = textureheight;
5298                 r_waterstate.camerawidth = camerawidth;
5299                 r_waterstate.cameraheight = cameraheight;
5300         }
5301
5302         if (r_waterstate.texturewidth)
5303         {
5304                 r_waterstate.enabled = true;
5305
5306                 // when doing a reduced render (HDR) we want to use a smaller area
5307                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5308                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5309
5310                 // set up variables that will be used in shader setup
5311                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5312                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5313                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5314                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5315         }
5316
5317         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5318         r_waterstate.numwaterplanes = 0;
5319 }
5320
5321 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5322 {
5323         int triangleindex, planeindex;
5324         const int *e;
5325         vec3_t vert[3];
5326         vec3_t normal;
5327         vec3_t center;
5328         mplane_t plane;
5329         r_waterstate_waterplane_t *p;
5330         texture_t *t = R_GetCurrentTexture(surface->texture);
5331
5332         // just use the first triangle with a valid normal for any decisions
5333         VectorClear(normal);
5334         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5335         {
5336                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5337                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5338                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5339                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5340                 if (VectorLength2(normal) >= 0.001)
5341                         break;
5342         }
5343
5344         VectorCopy(normal, plane.normal);
5345         VectorNormalize(plane.normal);
5346         plane.dist = DotProduct(vert[0], plane.normal);
5347         PlaneClassify(&plane);
5348         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5349         {
5350                 // skip backfaces (except if nocullface is set)
5351                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5352                         return;
5353                 VectorNegate(plane.normal, plane.normal);
5354                 plane.dist *= -1;
5355                 PlaneClassify(&plane);
5356         }
5357
5358
5359         // find a matching plane if there is one
5360         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5361                 if(p->camera_entity == t->camera_entity)
5362                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5363                                 break;
5364         if (planeindex >= r_waterstate.maxwaterplanes)
5365                 return; // nothing we can do, out of planes
5366
5367         // if this triangle does not fit any known plane rendered this frame, add one
5368         if (planeindex >= r_waterstate.numwaterplanes)
5369         {
5370                 // store the new plane
5371                 r_waterstate.numwaterplanes++;
5372                 p->plane = plane;
5373                 // clear materialflags and pvs
5374                 p->materialflags = 0;
5375                 p->pvsvalid = false;
5376                 p->camera_entity = t->camera_entity;
5377                 VectorCopy(surface->mins, p->mins);
5378                 VectorCopy(surface->maxs, p->maxs);
5379         }
5380         else
5381         {
5382                 // merge mins/maxs
5383                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5384                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5385                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5386                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5387                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5388                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5389         }
5390         // merge this surface's materialflags into the waterplane
5391         p->materialflags |= t->currentmaterialflags;
5392         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5393         {
5394                 // merge this surface's PVS into the waterplane
5395                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5396                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5397                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5398                 {
5399                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5400                         p->pvsvalid = true;
5401                 }
5402         }
5403 }
5404
5405 static void R_Water_ProcessPlanes(void)
5406 {
5407         int myscissor[4];
5408         r_refdef_view_t originalview;
5409         r_refdef_view_t myview;
5410         int planeindex;
5411         r_waterstate_waterplane_t *p;
5412         vec3_t visorigin;
5413
5414         originalview = r_refdef.view;
5415
5416         // make sure enough textures are allocated
5417         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5418         {
5419                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5420                 {
5421                         if (!p->texture_refraction)
5422                                 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);
5423                         if (!p->texture_refraction)
5424                                 goto error;
5425                 }
5426                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5427                 {
5428                         if (!p->texture_camera)
5429                                 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);
5430                         if (!p->texture_camera)
5431                                 goto error;
5432                 }
5433
5434                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5435                 {
5436                         if (!p->texture_reflection)
5437                                 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);
5438                         if (!p->texture_reflection)
5439                                 goto error;
5440                 }
5441         }
5442
5443         // render views
5444         r_refdef.view = originalview;
5445         r_refdef.view.showdebug = false;
5446         r_refdef.view.width = r_waterstate.waterwidth;
5447         r_refdef.view.height = r_waterstate.waterheight;
5448         r_refdef.view.useclipplane = true;
5449         myview = r_refdef.view;
5450         r_waterstate.renderingscene = true;
5451         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5452         {
5453                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5454                 {
5455                         r_refdef.view = myview;
5456                         if(r_water_scissormode.integer)
5457                         {
5458                                 R_SetupView(true);
5459                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5460                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5461                         }
5462
5463                         // render reflected scene and copy into texture
5464                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5465                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5466                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5467                         r_refdef.view.clipplane = p->plane;
5468
5469                         // reverse the cullface settings for this render
5470                         r_refdef.view.cullface_front = GL_FRONT;
5471                         r_refdef.view.cullface_back = GL_BACK;
5472                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5473                         {
5474                                 r_refdef.view.usecustompvs = true;
5475                                 if (p->pvsvalid)
5476                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5477                                 else
5478                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5479                         }
5480
5481                         R_ResetViewRendering3D();
5482                         R_ClearScreen(r_refdef.fogenabled);
5483                         if(r_water_scissormode.integer & 2)
5484                                 R_View_UpdateWithScissor(myscissor);
5485                         else
5486                                 R_View_Update();
5487                         if(r_water_scissormode.integer & 1)
5488                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5489                         R_RenderScene();
5490
5491                         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);
5492                 }
5493
5494                 // render the normal view scene and copy into texture
5495                 // (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)
5496                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5497                 {
5498                         r_refdef.view = myview;
5499                         if(r_water_scissormode.integer)
5500                         {
5501                                 R_SetupView(true);
5502                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5503                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5504                         }
5505
5506                         r_waterstate.renderingrefraction = true;
5507
5508                         r_refdef.view.clipplane = p->plane;
5509                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5510                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5511
5512                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5513                         {
5514                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5515                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5516                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5517                                 R_RenderView_UpdateViewVectors();
5518                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5519                                 {
5520                                         r_refdef.view.usecustompvs = true;
5521                                         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);
5522                                 }
5523                         }
5524
5525                         PlaneClassify(&r_refdef.view.clipplane);
5526
5527                         R_ResetViewRendering3D();
5528                         R_ClearScreen(r_refdef.fogenabled);
5529                         if(r_water_scissormode.integer & 2)
5530                                 R_View_UpdateWithScissor(myscissor);
5531                         else
5532                                 R_View_Update();
5533                         if(r_water_scissormode.integer & 1)
5534                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5535                         R_RenderScene();
5536
5537                         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);
5538                         r_waterstate.renderingrefraction = false;
5539                 }
5540                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5541                 {
5542                         r_refdef.view = myview;
5543
5544                         r_refdef.view.clipplane = p->plane;
5545                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5546                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5547
5548                         r_refdef.view.width = r_waterstate.camerawidth;
5549                         r_refdef.view.height = r_waterstate.cameraheight;
5550                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5551                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5552
5553                         if(p->camera_entity)
5554                         {
5555                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5556                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5557                         }
5558
5559                         // note: all of the view is used for displaying... so
5560                         // there is no use in scissoring
5561
5562                         // reverse the cullface settings for this render
5563                         r_refdef.view.cullface_front = GL_FRONT;
5564                         r_refdef.view.cullface_back = GL_BACK;
5565                         // also reverse the view matrix
5566                         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
5567                         R_RenderView_UpdateViewVectors();
5568                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5569                         {
5570                                 r_refdef.view.usecustompvs = true;
5571                                 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);
5572                         }
5573                         
5574                         // camera needs no clipplane
5575                         r_refdef.view.useclipplane = false;
5576
5577                         PlaneClassify(&r_refdef.view.clipplane);
5578
5579                         R_ResetViewRendering3D();
5580                         R_ClearScreen(r_refdef.fogenabled);
5581                         R_View_Update();
5582                         R_RenderScene();
5583
5584                         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);
5585                         r_waterstate.renderingrefraction = false;
5586                 }
5587
5588         }
5589         r_waterstate.renderingscene = false;
5590         r_refdef.view = originalview;
5591         R_ResetViewRendering3D();
5592         R_ClearScreen(r_refdef.fogenabled);
5593         R_View_Update();
5594         return;
5595 error:
5596         r_refdef.view = originalview;
5597         r_waterstate.renderingscene = false;
5598         Cvar_SetValueQuick(&r_water, 0);
5599         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5600         return;
5601 }
5602
5603 void R_Bloom_StartFrame(void)
5604 {
5605         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5606
5607         switch(vid.renderpath)
5608         {
5609         case RENDERPATH_GL20:
5610         case RENDERPATH_D3D9:
5611         case RENDERPATH_D3D10:
5612         case RENDERPATH_D3D11:
5613         case RENDERPATH_SOFT:
5614         case RENDERPATH_GLES2:
5615                 break;
5616         case RENDERPATH_GL13:
5617         case RENDERPATH_GL11:
5618                 return;
5619         }
5620
5621         // set bloomwidth and bloomheight to the bloom resolution that will be
5622         // used (often less than the screen resolution for faster rendering)
5623         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5624         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5625         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5626         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5627         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5628
5629         // calculate desired texture sizes
5630         if (vid.support.arb_texture_non_power_of_two)
5631         {
5632                 screentexturewidth = r_refdef.view.width;
5633                 screentextureheight = r_refdef.view.height;
5634                 bloomtexturewidth = r_bloomstate.bloomwidth;
5635                 bloomtextureheight = r_bloomstate.bloomheight;
5636         }
5637         else
5638         {
5639                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5640                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5641                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5642                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5643         }
5644
5645         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))
5646         {
5647                 Cvar_SetValueQuick(&r_hdr, 0);
5648                 Cvar_SetValueQuick(&r_bloom, 0);
5649                 Cvar_SetValueQuick(&r_motionblur, 0);
5650                 Cvar_SetValueQuick(&r_damageblur, 0);
5651         }
5652
5653         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)))
5654                 screentexturewidth = screentextureheight = 0;
5655         if (!r_hdr.integer && !r_bloom.integer)
5656                 bloomtexturewidth = bloomtextureheight = 0;
5657
5658         // allocate textures as needed
5659         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5660         {
5661                 if (r_bloomstate.texture_screen)
5662                         R_FreeTexture(r_bloomstate.texture_screen);
5663                 r_bloomstate.texture_screen = NULL;
5664                 r_bloomstate.screentexturewidth = screentexturewidth;
5665                 r_bloomstate.screentextureheight = screentextureheight;
5666                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5667                         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);
5668         }
5669         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5670         {
5671                 if (r_bloomstate.texture_bloom)
5672                         R_FreeTexture(r_bloomstate.texture_bloom);
5673                 r_bloomstate.texture_bloom = NULL;
5674                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5675                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5676                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5677                         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);
5678         }
5679
5680         // when doing a reduced render (HDR) we want to use a smaller area
5681         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5682         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5683         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5684         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5685         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5686
5687         // set up a texcoord array for the full resolution screen image
5688         // (we have to keep this around to copy back during final render)
5689         r_bloomstate.screentexcoord2f[0] = 0;
5690         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5691         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5692         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5693         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5694         r_bloomstate.screentexcoord2f[5] = 0;
5695         r_bloomstate.screentexcoord2f[6] = 0;
5696         r_bloomstate.screentexcoord2f[7] = 0;
5697
5698         // set up a texcoord array for the reduced resolution bloom image
5699         // (which will be additive blended over the screen image)
5700         r_bloomstate.bloomtexcoord2f[0] = 0;
5701         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5702         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5703         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5704         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5705         r_bloomstate.bloomtexcoord2f[5] = 0;
5706         r_bloomstate.bloomtexcoord2f[6] = 0;
5707         r_bloomstate.bloomtexcoord2f[7] = 0;
5708
5709         switch(vid.renderpath)
5710         {
5711         case RENDERPATH_GL11:
5712         case RENDERPATH_GL13:
5713         case RENDERPATH_GL20:
5714         case RENDERPATH_SOFT:
5715         case RENDERPATH_GLES2:
5716                 break;
5717         case RENDERPATH_D3D9:
5718         case RENDERPATH_D3D10:
5719         case RENDERPATH_D3D11:
5720                 {
5721                         int i;
5722                         for (i = 0;i < 4;i++)
5723                         {
5724                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5725                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5726                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5727                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5728                         }
5729                 }
5730                 break;
5731         }
5732
5733         if (r_hdr.integer || r_bloom.integer)
5734         {
5735                 r_bloomstate.enabled = true;
5736                 r_bloomstate.hdr = r_hdr.integer != 0;
5737         }
5738
5739         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);
5740 }
5741
5742 void R_Bloom_CopyBloomTexture(float colorscale)
5743 {
5744         r_refdef.stats.bloom++;
5745
5746         // scale down screen texture to the bloom texture size
5747         CHECKGLERROR
5748         R_SetViewport(&r_bloomstate.viewport);
5749         GL_BlendFunc(GL_ONE, GL_ZERO);
5750         GL_Color(colorscale, colorscale, colorscale, 1);
5751         // 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...
5752         switch(vid.renderpath)
5753         {
5754         case RENDERPATH_GL11:
5755         case RENDERPATH_GL13:
5756         case RENDERPATH_GL20:
5757         case RENDERPATH_SOFT:
5758         case RENDERPATH_GLES2:
5759                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5760                 break;
5761         case RENDERPATH_D3D9:
5762         case RENDERPATH_D3D10:
5763         case RENDERPATH_D3D11:
5764                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5765                 break;
5766         }
5767         // TODO: do boxfilter scale-down in shader?
5768         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5769         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5770         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5771
5772         // we now have a bloom image in the framebuffer
5773         // copy it into the bloom image texture for later processing
5774         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);
5775         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5776 }
5777
5778 void R_Bloom_CopyHDRTexture(void)
5779 {
5780         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);
5781         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5782 }
5783
5784 void R_Bloom_MakeTexture(void)
5785 {
5786         int x, range, dir;
5787         float xoffset, yoffset, r, brighten;
5788
5789         r_refdef.stats.bloom++;
5790
5791         R_ResetViewRendering2D();
5792
5793         // we have a bloom image in the framebuffer
5794         CHECKGLERROR
5795         R_SetViewport(&r_bloomstate.viewport);
5796
5797         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5798         {
5799                 x *= 2;
5800                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5801                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5802                 GL_Color(r,r,r,1);
5803                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5804                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5805                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5806                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5807
5808                 // copy the vertically blurred bloom view to a texture
5809                 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);
5810                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5811         }
5812
5813         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5814         brighten = r_bloom_brighten.value;
5815         if (r_hdr.integer)
5816                 brighten *= r_hdr_range.value;
5817         brighten = sqrt(brighten);
5818         if(range >= 1)
5819                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5820         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5821
5822         for (dir = 0;dir < 2;dir++)
5823         {
5824                 // blend on at multiple vertical offsets to achieve a vertical blur
5825                 // TODO: do offset blends using GLSL
5826                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5827                 GL_BlendFunc(GL_ONE, GL_ZERO);
5828                 for (x = -range;x <= range;x++)
5829                 {
5830                         if (!dir){xoffset = 0;yoffset = x;}
5831                         else {xoffset = x;yoffset = 0;}
5832                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5833                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5834                         // compute a texcoord array with the specified x and y offset
5835                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5836                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5837                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5838                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5839                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5840                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5841                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5842                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5843                         // this r value looks like a 'dot' particle, fading sharply to
5844                         // black at the edges
5845                         // (probably not realistic but looks good enough)
5846                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5847                         //r = brighten/(range*2+1);
5848                         r = brighten / (range * 2 + 1);
5849                         if(range >= 1)
5850                                 r *= (1 - x*x/(float)(range*range));
5851                         GL_Color(r, r, r, 1);
5852                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5853                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5854                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5855                         GL_BlendFunc(GL_ONE, GL_ONE);
5856                 }
5857
5858                 // copy the vertically blurred bloom view to a texture
5859                 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);
5860                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5861         }
5862 }
5863
5864 void R_HDR_RenderBloomTexture(void)
5865 {
5866         int oldwidth, oldheight;
5867         float oldcolorscale;
5868         qboolean oldwaterstate;
5869
5870         oldwaterstate = r_waterstate.enabled;
5871         oldcolorscale = r_refdef.view.colorscale;
5872         oldwidth = r_refdef.view.width;
5873         oldheight = r_refdef.view.height;
5874         r_refdef.view.width = r_bloomstate.bloomwidth;
5875         r_refdef.view.height = r_bloomstate.bloomheight;
5876
5877         if(r_hdr.integer < 2)
5878                 r_waterstate.enabled = false;
5879
5880         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5881         // TODO: add exposure compensation features
5882         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5883
5884         r_refdef.view.showdebug = false;
5885         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5886
5887         R_ResetViewRendering3D();
5888
5889         R_ClearScreen(r_refdef.fogenabled);
5890         if (r_timereport_active)
5891                 R_TimeReport("HDRclear");
5892
5893         R_View_Update();
5894         if (r_timereport_active)
5895                 R_TimeReport("visibility");
5896
5897         // only do secondary renders with HDR if r_hdr is 2 or higher
5898         r_waterstate.numwaterplanes = 0;
5899         if (r_waterstate.enabled)
5900                 R_RenderWaterPlanes();
5901
5902         r_refdef.view.showdebug = true;
5903         R_RenderScene();
5904         r_waterstate.numwaterplanes = 0;
5905
5906         R_ResetViewRendering2D();
5907
5908         R_Bloom_CopyHDRTexture();
5909         R_Bloom_MakeTexture();
5910
5911         // restore the view settings
5912         r_waterstate.enabled = oldwaterstate;
5913         r_refdef.view.width = oldwidth;
5914         r_refdef.view.height = oldheight;
5915         r_refdef.view.colorscale = oldcolorscale;
5916
5917         R_ResetViewRendering3D();
5918
5919         R_ClearScreen(r_refdef.fogenabled);
5920         if (r_timereport_active)
5921                 R_TimeReport("viewclear");
5922 }
5923
5924 static void R_BlendView(void)
5925 {
5926         unsigned int permutation;
5927         float uservecs[4][4];
5928
5929         switch (vid.renderpath)
5930         {
5931         case RENDERPATH_GL20:
5932         case RENDERPATH_D3D9:
5933         case RENDERPATH_D3D10:
5934         case RENDERPATH_D3D11:
5935         case RENDERPATH_SOFT:
5936         case RENDERPATH_GLES2:
5937                 permutation =
5938                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5939                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5940                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5941                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5942                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5943
5944                 if (r_bloomstate.texture_screen)
5945                 {
5946                         // make sure the buffer is available
5947                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5948
5949                         R_ResetViewRendering2D();
5950
5951                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5952                         {
5953                                 // declare variables
5954                                 float speed;
5955                                 static float avgspeed;
5956
5957                                 speed = VectorLength(cl.movement_velocity);
5958
5959                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5960                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5961
5962                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5963                                 speed = bound(0, speed, 1);
5964                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5965
5966                                 // calculate values into a standard alpha
5967                                 cl.motionbluralpha = 1 - exp(-
5968                                                 (
5969                                                  (r_motionblur.value * speed / 80)
5970                                                  +
5971                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5972                                                 )
5973                                                 /
5974                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5975                                            );
5976
5977                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5978                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5979                                 // apply the blur
5980                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5981                                 {
5982                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5983                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5984                                         switch(vid.renderpath)
5985                                         {
5986                                         case RENDERPATH_GL11:
5987                                         case RENDERPATH_GL13:
5988                                         case RENDERPATH_GL20:
5989                                         case RENDERPATH_SOFT:
5990                                         case RENDERPATH_GLES2:
5991                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5992                                                 break;
5993                                         case RENDERPATH_D3D9:
5994                                         case RENDERPATH_D3D10:
5995                                         case RENDERPATH_D3D11:
5996                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5997                                                 break;
5998                                         }
5999                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6000                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6001                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6002                                 }
6003                         }
6004
6005                         // copy view into the screen texture
6006                         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);
6007                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6008                 }
6009                 else if (!r_bloomstate.texture_bloom)
6010                 {
6011                         // we may still have to do view tint...
6012                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6013                         {
6014                                 // apply a color tint to the whole view
6015                                 R_ResetViewRendering2D();
6016                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6017                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6018                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6019                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6020                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6021                         }
6022                         break; // no screen processing, no bloom, skip it
6023                 }
6024
6025                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6026                 {
6027                         // render simple bloom effect
6028                         // copy the screen and shrink it and darken it for the bloom process
6029                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6030                         // make the bloom texture
6031                         R_Bloom_MakeTexture();
6032                 }
6033
6034 #if _MSC_VER >= 1400
6035 #define sscanf sscanf_s
6036 #endif
6037                 memset(uservecs, 0, sizeof(uservecs));
6038                 if (r_glsl_postprocess_uservec1_enable.integer)
6039                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6040                 if (r_glsl_postprocess_uservec2_enable.integer)
6041                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6042                 if (r_glsl_postprocess_uservec3_enable.integer)
6043                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6044                 if (r_glsl_postprocess_uservec4_enable.integer)
6045                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6046
6047                 R_ResetViewRendering2D();
6048                 GL_Color(1, 1, 1, 1);
6049                 GL_BlendFunc(GL_ONE, GL_ZERO);
6050
6051                 switch(vid.renderpath)
6052                 {
6053                 case RENDERPATH_GL20:
6054                 case RENDERPATH_GLES2:
6055                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6056                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6057                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6058                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6059                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6060                         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]);
6061                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6062                         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]);
6063                         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]);
6064                         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]);
6065                         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]);
6066                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6067                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6068                         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);
6069                         break;
6070                 case RENDERPATH_D3D9:
6071 #ifdef SUPPORTD3D
6072                         // 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...
6073                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6074                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6075                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6076                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6077                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6078                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6079                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6080                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6081                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6082                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6083                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6084                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6085                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6086                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6087 #endif
6088                         break;
6089                 case RENDERPATH_D3D10:
6090                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6091                         break;
6092                 case RENDERPATH_D3D11:
6093                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6094                         break;
6095                 case RENDERPATH_SOFT:
6096                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6097                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6098                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6099                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6100                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6101                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6102                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6103                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6104                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6105                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6106                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6107                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6108                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6109                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6110                         break;
6111                 default:
6112                         break;
6113                 }
6114                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6115                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6116                 break;
6117         case RENDERPATH_GL13:
6118         case RENDERPATH_GL11:
6119                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6120                 {
6121                         // apply a color tint to the whole view
6122                         R_ResetViewRendering2D();
6123                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6124                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6125                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6126                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6127                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6128                 }
6129                 break;
6130         }
6131 }
6132
6133 matrix4x4_t r_waterscrollmatrix;
6134
6135 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6136 {
6137         if (r_refdef.fog_density)
6138         {
6139                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6140                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6141                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6142
6143                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6144                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6145                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6146                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6147
6148                 {
6149                         vec3_t fogvec;
6150                         VectorCopy(r_refdef.fogcolor, fogvec);
6151                         //   color.rgb *= ContrastBoost * SceneBrightness;
6152                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6153                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6154                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6155                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6156                 }
6157         }
6158 }
6159
6160 void R_UpdateVariables(void)
6161 {
6162         R_Textures_Frame();
6163
6164         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6165
6166         r_refdef.farclip = r_farclip_base.value;
6167         if (r_refdef.scene.worldmodel)
6168                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6169         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6170
6171         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6172                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6173         r_refdef.polygonfactor = 0;
6174         r_refdef.polygonoffset = 0;
6175         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6176         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6177
6178         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6179         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6180         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6181         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6182         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6183         if (FAKELIGHT_ENABLED)
6184         {
6185                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6186         }
6187         if (r_showsurfaces.integer)
6188         {
6189                 r_refdef.scene.rtworld = false;
6190                 r_refdef.scene.rtworldshadows = false;
6191                 r_refdef.scene.rtdlight = false;
6192                 r_refdef.scene.rtdlightshadows = false;
6193                 r_refdef.lightmapintensity = 0;
6194         }
6195
6196         if (gamemode == GAME_NEHAHRA)
6197         {
6198                 if (gl_fogenable.integer)
6199                 {
6200                         r_refdef.oldgl_fogenable = true;
6201                         r_refdef.fog_density = gl_fogdensity.value;
6202                         r_refdef.fog_red = gl_fogred.value;
6203                         r_refdef.fog_green = gl_foggreen.value;
6204                         r_refdef.fog_blue = gl_fogblue.value;
6205                         r_refdef.fog_alpha = 1;
6206                         r_refdef.fog_start = 0;
6207                         r_refdef.fog_end = gl_skyclip.value;
6208                         r_refdef.fog_height = 1<<30;
6209                         r_refdef.fog_fadedepth = 128;
6210                 }
6211                 else if (r_refdef.oldgl_fogenable)
6212                 {
6213                         r_refdef.oldgl_fogenable = false;
6214                         r_refdef.fog_density = 0;
6215                         r_refdef.fog_red = 0;
6216                         r_refdef.fog_green = 0;
6217                         r_refdef.fog_blue = 0;
6218                         r_refdef.fog_alpha = 0;
6219                         r_refdef.fog_start = 0;
6220                         r_refdef.fog_end = 0;
6221                         r_refdef.fog_height = 1<<30;
6222                         r_refdef.fog_fadedepth = 128;
6223                 }
6224         }
6225
6226         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6227         r_refdef.fog_start = max(0, r_refdef.fog_start);
6228         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6229
6230         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6231
6232         if (r_refdef.fog_density && r_drawfog.integer)
6233         {
6234                 r_refdef.fogenabled = true;
6235                 // this is the point where the fog reaches 0.9986 alpha, which we
6236                 // consider a good enough cutoff point for the texture
6237                 // (0.9986 * 256 == 255.6)
6238                 if (r_fog_exp2.integer)
6239                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6240                 else
6241                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6242                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6243                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6244                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6245                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6246                         R_BuildFogHeightTexture();
6247                 // fog color was already set
6248                 // update the fog texture
6249                 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)
6250                         R_BuildFogTexture();
6251                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6252                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6253         }
6254         else
6255                 r_refdef.fogenabled = false;
6256
6257         switch(vid.renderpath)
6258         {
6259         case RENDERPATH_GL20:
6260         case RENDERPATH_D3D9:
6261         case RENDERPATH_D3D10:
6262         case RENDERPATH_D3D11:
6263         case RENDERPATH_SOFT:
6264         case RENDERPATH_GLES2:
6265                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6266                 {
6267                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6268                         {
6269                                 // build GLSL gamma texture
6270 #define RAMPWIDTH 256
6271                                 unsigned short ramp[RAMPWIDTH * 3];
6272                                 unsigned char rampbgr[RAMPWIDTH][4];
6273                                 int i;
6274
6275                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6276
6277                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6278                                 for(i = 0; i < RAMPWIDTH; ++i)
6279                                 {
6280                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6281                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6282                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6283                                         rampbgr[i][3] = 0;
6284                                 }
6285                                 if (r_texture_gammaramps)
6286                                 {
6287                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6288                                 }
6289                                 else
6290                                 {
6291                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6292                                 }
6293                         }
6294                 }
6295                 else
6296                 {
6297                         // remove GLSL gamma texture
6298                 }
6299                 break;
6300         case RENDERPATH_GL13:
6301         case RENDERPATH_GL11:
6302                 break;
6303         }
6304 }
6305
6306 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6307 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6308 /*
6309 ================
6310 R_SelectScene
6311 ================
6312 */
6313 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6314         if( scenetype != r_currentscenetype ) {
6315                 // store the old scenetype
6316                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6317                 r_currentscenetype = scenetype;
6318                 // move in the new scene
6319                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6320         }
6321 }
6322
6323 /*
6324 ================
6325 R_GetScenePointer
6326 ================
6327 */
6328 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6329 {
6330         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6331         if( scenetype == r_currentscenetype ) {
6332                 return &r_refdef.scene;
6333         } else {
6334                 return &r_scenes_store[ scenetype ];
6335         }
6336 }
6337
6338 /*
6339 ================
6340 R_RenderView
6341 ================
6342 */
6343 int dpsoftrast_test;
6344 void R_RenderView(void)
6345 {
6346         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6347
6348         dpsoftrast_test = r_test.integer;
6349
6350         if (r_timereport_active)
6351                 R_TimeReport("start");
6352         r_textureframe++; // used only by R_GetCurrentTexture
6353         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6354
6355         if(R_CompileShader_CheckStaticParms())
6356                 R_GLSL_Restart_f();
6357
6358         if (!r_drawentities.integer)
6359                 r_refdef.scene.numentities = 0;
6360
6361         R_AnimCache_ClearCache();
6362         R_FrameData_NewFrame();
6363
6364         /* adjust for stereo display */
6365         if(R_Stereo_Active())
6366         {
6367                 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);
6368                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6369         }
6370
6371         if (r_refdef.view.isoverlay)
6372         {
6373                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6374                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6375                 R_TimeReport("depthclear");
6376
6377                 r_refdef.view.showdebug = false;
6378
6379                 r_waterstate.enabled = false;
6380                 r_waterstate.numwaterplanes = 0;
6381
6382                 R_RenderScene();
6383
6384                 r_refdef.view.matrix = originalmatrix;
6385
6386                 CHECKGLERROR
6387                 return;
6388         }
6389
6390         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6391         {
6392                 r_refdef.view.matrix = originalmatrix;
6393                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6394         }
6395
6396         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6397
6398         R_RenderView_UpdateViewVectors();
6399
6400         R_Shadow_UpdateWorldLightSelection();
6401
6402         R_Bloom_StartFrame();
6403         R_Water_StartFrame();
6404
6405         CHECKGLERROR
6406         if (r_timereport_active)
6407                 R_TimeReport("viewsetup");
6408
6409         R_ResetViewRendering3D();
6410
6411         if (r_refdef.view.clear || r_refdef.fogenabled)
6412         {
6413                 R_ClearScreen(r_refdef.fogenabled);
6414                 if (r_timereport_active)
6415                         R_TimeReport("viewclear");
6416         }
6417         r_refdef.view.clear = true;
6418
6419         // this produces a bloom texture to be used in R_BlendView() later
6420         if (r_hdr.integer && r_bloomstate.bloomwidth)
6421         {
6422                 R_HDR_RenderBloomTexture();
6423                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6424                 r_textureframe++; // used only by R_GetCurrentTexture
6425         }
6426
6427         r_refdef.view.showdebug = true;
6428
6429         R_View_Update();
6430         if (r_timereport_active)
6431                 R_TimeReport("visibility");
6432
6433         r_waterstate.numwaterplanes = 0;
6434         if (r_waterstate.enabled)
6435                 R_RenderWaterPlanes();
6436
6437         R_RenderScene();
6438         r_waterstate.numwaterplanes = 0;
6439
6440         R_BlendView();
6441         if (r_timereport_active)
6442                 R_TimeReport("blendview");
6443
6444         GL_Scissor(0, 0, vid.width, vid.height);
6445         GL_ScissorTest(false);
6446
6447         r_refdef.view.matrix = originalmatrix;
6448
6449         CHECKGLERROR
6450 }
6451
6452 void R_RenderWaterPlanes(void)
6453 {
6454         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6455         {
6456                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6457                 if (r_timereport_active)
6458                         R_TimeReport("waterworld");
6459         }
6460
6461         // don't let sound skip if going slow
6462         if (r_refdef.scene.extraupdate)
6463                 S_ExtraUpdate ();
6464
6465         R_DrawModelsAddWaterPlanes();
6466         if (r_timereport_active)
6467                 R_TimeReport("watermodels");
6468
6469         if (r_waterstate.numwaterplanes)
6470         {
6471                 R_Water_ProcessPlanes();
6472                 if (r_timereport_active)
6473                         R_TimeReport("waterscenes");
6474         }
6475 }
6476
6477 extern void R_DrawLightningBeams (void);
6478 extern void VM_CL_AddPolygonsToMeshQueue (void);
6479 extern void R_DrawPortals (void);
6480 extern cvar_t cl_locs_show;
6481 static void R_DrawLocs(void);
6482 static void R_DrawEntityBBoxes(void);
6483 static void R_DrawModelDecals(void);
6484 extern void R_DrawModelShadows(void);
6485 extern void R_DrawModelShadowMaps(void);
6486 extern cvar_t cl_decals_newsystem;
6487 extern qboolean r_shadow_usingdeferredprepass;
6488 void R_RenderScene(void)
6489 {
6490         qboolean shadowmapping = false;
6491
6492         if (r_timereport_active)
6493                 R_TimeReport("beginscene");
6494
6495         r_refdef.stats.renders++;
6496
6497         R_UpdateFogColor();
6498
6499         // don't let sound skip if going slow
6500         if (r_refdef.scene.extraupdate)
6501                 S_ExtraUpdate ();
6502
6503         R_MeshQueue_BeginScene();
6504
6505         R_SkyStartFrame();
6506
6507         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);
6508
6509         if (r_timereport_active)
6510                 R_TimeReport("skystartframe");
6511
6512         if (cl.csqc_vidvars.drawworld)
6513         {
6514                 // don't let sound skip if going slow
6515                 if (r_refdef.scene.extraupdate)
6516                         S_ExtraUpdate ();
6517
6518                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6519                 {
6520                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6521                         if (r_timereport_active)
6522                                 R_TimeReport("worldsky");
6523                 }
6524
6525                 if (R_DrawBrushModelsSky() && r_timereport_active)
6526                         R_TimeReport("bmodelsky");
6527
6528                 if (skyrendermasked && skyrenderlater)
6529                 {
6530                         // we have to force off the water clipping plane while rendering sky
6531                         R_SetupView(false);
6532                         R_Sky();
6533                         R_SetupView(true);
6534                         if (r_timereport_active)
6535                                 R_TimeReport("sky");
6536                 }
6537         }
6538
6539         R_AnimCache_CacheVisibleEntities();
6540         if (r_timereport_active)
6541                 R_TimeReport("animation");
6542
6543         R_Shadow_PrepareLights();
6544         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6545                 R_Shadow_PrepareModelShadows();
6546         if (r_timereport_active)
6547                 R_TimeReport("preparelights");
6548
6549         if (R_Shadow_ShadowMappingEnabled())
6550                 shadowmapping = true;
6551
6552         if (r_shadow_usingdeferredprepass)
6553                 R_Shadow_DrawPrepass();
6554
6555         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6556         {
6557                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6558                 if (r_timereport_active)
6559                         R_TimeReport("worlddepth");
6560         }
6561         if (r_depthfirst.integer >= 2)
6562         {
6563                 R_DrawModelsDepth();
6564                 if (r_timereport_active)
6565                         R_TimeReport("modeldepth");
6566         }
6567
6568         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6569         {
6570                 R_DrawModelShadowMaps();
6571                 R_ResetViewRendering3D();
6572                 // don't let sound skip if going slow
6573                 if (r_refdef.scene.extraupdate)
6574                         S_ExtraUpdate ();
6575         }
6576
6577         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6578         {
6579                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6580                 if (r_timereport_active)
6581                         R_TimeReport("world");
6582         }
6583
6584         // don't let sound skip if going slow
6585         if (r_refdef.scene.extraupdate)
6586                 S_ExtraUpdate ();
6587
6588         R_DrawModels();
6589         if (r_timereport_active)
6590                 R_TimeReport("models");
6591
6592         // don't let sound skip if going slow
6593         if (r_refdef.scene.extraupdate)
6594                 S_ExtraUpdate ();
6595
6596         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6597         {
6598                 R_DrawModelShadows();
6599                 R_ResetViewRendering3D();
6600                 // don't let sound skip if going slow
6601                 if (r_refdef.scene.extraupdate)
6602                         S_ExtraUpdate ();
6603         }
6604
6605         if (!r_shadow_usingdeferredprepass)
6606         {
6607                 R_Shadow_DrawLights();
6608                 if (r_timereport_active)
6609                         R_TimeReport("rtlights");
6610         }
6611
6612         // don't let sound skip if going slow
6613         if (r_refdef.scene.extraupdate)
6614                 S_ExtraUpdate ();
6615
6616         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6617         {
6618                 R_DrawModelShadows();
6619                 R_ResetViewRendering3D();
6620                 // don't let sound skip if going slow
6621                 if (r_refdef.scene.extraupdate)
6622                         S_ExtraUpdate ();
6623         }
6624
6625         if (cl.csqc_vidvars.drawworld)
6626         {
6627                 if (cl_decals_newsystem.integer)
6628                 {
6629                         R_DrawModelDecals();
6630                         if (r_timereport_active)
6631                                 R_TimeReport("modeldecals");
6632                 }
6633                 else
6634                 {
6635                         R_DrawDecals();
6636                         if (r_timereport_active)
6637                                 R_TimeReport("decals");
6638                 }
6639
6640                 R_DrawParticles();
6641                 if (r_timereport_active)
6642                         R_TimeReport("particles");
6643
6644                 R_DrawExplosions();
6645                 if (r_timereport_active)
6646                         R_TimeReport("explosions");
6647
6648                 R_DrawLightningBeams();
6649                 if (r_timereport_active)
6650                         R_TimeReport("lightning");
6651         }
6652
6653         VM_CL_AddPolygonsToMeshQueue();
6654
6655         if (r_refdef.view.showdebug)
6656         {
6657                 if (cl_locs_show.integer)
6658                 {
6659                         R_DrawLocs();
6660                         if (r_timereport_active)
6661                                 R_TimeReport("showlocs");
6662                 }
6663
6664                 if (r_drawportals.integer)
6665                 {
6666                         R_DrawPortals();
6667                         if (r_timereport_active)
6668                                 R_TimeReport("portals");
6669                 }
6670
6671                 if (r_showbboxes.value > 0)
6672                 {
6673                         R_DrawEntityBBoxes();
6674                         if (r_timereport_active)
6675                                 R_TimeReport("bboxes");
6676                 }
6677         }
6678
6679         R_MeshQueue_RenderTransparent();
6680         if (r_timereport_active)
6681                 R_TimeReport("drawtrans");
6682
6683         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))
6684         {
6685                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6686                 if (r_timereport_active)
6687                         R_TimeReport("worlddebug");
6688                 R_DrawModelsDebug();
6689                 if (r_timereport_active)
6690                         R_TimeReport("modeldebug");
6691         }
6692
6693         if (cl.csqc_vidvars.drawworld)
6694         {
6695                 R_Shadow_DrawCoronas();
6696                 if (r_timereport_active)
6697                         R_TimeReport("coronas");
6698         }
6699
6700 #if 0
6701         {
6702                 GL_DepthTest(false);
6703                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6704                 GL_Color(1, 1, 1, 1);
6705                 qglBegin(GL_POLYGON);
6706                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6707                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6708                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6709                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6710                 qglEnd();
6711                 qglBegin(GL_POLYGON);
6712                 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]);
6713                 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]);
6714                 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]);
6715                 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]);
6716                 qglEnd();
6717                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6718         }
6719 #endif
6720
6721         // don't let sound skip if going slow
6722         if (r_refdef.scene.extraupdate)
6723                 S_ExtraUpdate ();
6724
6725         R_ResetViewRendering2D();
6726 }
6727
6728 static const unsigned short bboxelements[36] =
6729 {
6730         5, 1, 3, 5, 3, 7,
6731         6, 2, 0, 6, 0, 4,
6732         7, 3, 2, 7, 2, 6,
6733         4, 0, 1, 4, 1, 5,
6734         4, 5, 7, 4, 7, 6,
6735         1, 0, 2, 1, 2, 3,
6736 };
6737
6738 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6739 {
6740         int i;
6741         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6742
6743         RSurf_ActiveWorldEntity();
6744
6745         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6746         GL_DepthMask(false);
6747         GL_DepthRange(0, 1);
6748         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6749 //      R_Mesh_ResetTextureState();
6750
6751         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6752         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6753         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6754         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6755         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6756         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6757         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6758         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6759         R_FillColors(color4f, 8, cr, cg, cb, ca);
6760         if (r_refdef.fogenabled)
6761         {
6762                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6763                 {
6764                         f1 = RSurf_FogVertex(v);
6765                         f2 = 1 - f1;
6766                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6767                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6768                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6769                 }
6770         }
6771         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6772         R_Mesh_ResetTextureState();
6773         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6774         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6775 }
6776
6777 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6778 {
6779         int i;
6780         float color[4];
6781         prvm_edict_t *edict;
6782         prvm_prog_t *prog_save = prog;
6783
6784         // this function draws bounding boxes of server entities
6785         if (!sv.active)
6786                 return;
6787
6788         GL_CullFace(GL_NONE);
6789         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6790
6791         prog = 0;
6792         SV_VM_Begin();
6793         for (i = 0;i < numsurfaces;i++)
6794         {
6795                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6796                 switch ((int)edict->fields.server->solid)
6797                 {
6798                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6799                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6800                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6801                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6802                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6803                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6804                 }
6805                 color[3] *= r_showbboxes.value;
6806                 color[3] = bound(0, color[3], 1);
6807                 GL_DepthTest(!r_showdisabledepthtest.integer);
6808                 GL_CullFace(r_refdef.view.cullface_front);
6809                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6810         }
6811         SV_VM_End();
6812         prog = prog_save;
6813 }
6814
6815 static void R_DrawEntityBBoxes(void)
6816 {
6817         int i;
6818         prvm_edict_t *edict;
6819         vec3_t center;
6820         prvm_prog_t *prog_save = prog;
6821
6822         // this function draws bounding boxes of server entities
6823         if (!sv.active)
6824                 return;
6825
6826         prog = 0;
6827         SV_VM_Begin();
6828         for (i = 0;i < prog->num_edicts;i++)
6829         {
6830                 edict = PRVM_EDICT_NUM(i);
6831                 if (edict->priv.server->free)
6832                         continue;
6833                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6834                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6835                         continue;
6836                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6837                         continue;
6838                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6839                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6840         }
6841         SV_VM_End();
6842         prog = prog_save;
6843 }
6844
6845 static const int nomodelelement3i[24] =
6846 {
6847         5, 2, 0,
6848         5, 1, 2,
6849         5, 0, 3,
6850         5, 3, 1,
6851         0, 2, 4,
6852         2, 1, 4,
6853         3, 0, 4,
6854         1, 3, 4
6855 };
6856
6857 static const unsigned short nomodelelement3s[24] =
6858 {
6859         5, 2, 0,
6860         5, 1, 2,
6861         5, 0, 3,
6862         5, 3, 1,
6863         0, 2, 4,
6864         2, 1, 4,
6865         3, 0, 4,
6866         1, 3, 4
6867 };
6868
6869 static const float nomodelvertex3f[6*3] =
6870 {
6871         -16,   0,   0,
6872          16,   0,   0,
6873           0, -16,   0,
6874           0,  16,   0,
6875           0,   0, -16,
6876           0,   0,  16
6877 };
6878
6879 static const float nomodelcolor4f[6*4] =
6880 {
6881         0.0f, 0.0f, 0.5f, 1.0f,
6882         0.0f, 0.0f, 0.5f, 1.0f,
6883         0.0f, 0.5f, 0.0f, 1.0f,
6884         0.0f, 0.5f, 0.0f, 1.0f,
6885         0.5f, 0.0f, 0.0f, 1.0f,
6886         0.5f, 0.0f, 0.0f, 1.0f
6887 };
6888
6889 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6890 {
6891         int i;
6892         float f1, f2, *c;
6893         float color4f[6*4];
6894
6895         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);
6896
6897         // this is only called once per entity so numsurfaces is always 1, and
6898         // surfacelist is always {0}, so this code does not handle batches
6899
6900         if (rsurface.ent_flags & RENDER_ADDITIVE)
6901         {
6902                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6903                 GL_DepthMask(false);
6904         }
6905         else if (rsurface.colormod[3] < 1)
6906         {
6907                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6908                 GL_DepthMask(false);
6909         }
6910         else
6911         {
6912                 GL_BlendFunc(GL_ONE, GL_ZERO);
6913                 GL_DepthMask(true);
6914         }
6915         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6916         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6917         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6918         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6919         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6920         for (i = 0, c = color4f;i < 6;i++, c += 4)
6921         {
6922                 c[0] *= rsurface.colormod[0];
6923                 c[1] *= rsurface.colormod[1];
6924                 c[2] *= rsurface.colormod[2];
6925                 c[3] *= rsurface.colormod[3];
6926         }
6927         if (r_refdef.fogenabled)
6928         {
6929                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6930                 {
6931                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6932                         f2 = 1 - f1;
6933                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6934                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6935                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6936                 }
6937         }
6938 //      R_Mesh_ResetTextureState();
6939         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6940         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6941         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6942 }
6943
6944 void R_DrawNoModel(entity_render_t *ent)
6945 {
6946         vec3_t org;
6947         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6948         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6949                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6950         else
6951                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6952 }
6953
6954 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6955 {
6956         vec3_t right1, right2, diff, normal;
6957
6958         VectorSubtract (org2, org1, normal);
6959
6960         // calculate 'right' vector for start
6961         VectorSubtract (r_refdef.view.origin, org1, diff);
6962         CrossProduct (normal, diff, right1);
6963         VectorNormalize (right1);
6964
6965         // calculate 'right' vector for end
6966         VectorSubtract (r_refdef.view.origin, org2, diff);
6967         CrossProduct (normal, diff, right2);
6968         VectorNormalize (right2);
6969
6970         vert[ 0] = org1[0] + width * right1[0];
6971         vert[ 1] = org1[1] + width * right1[1];
6972         vert[ 2] = org1[2] + width * right1[2];
6973         vert[ 3] = org1[0] - width * right1[0];
6974         vert[ 4] = org1[1] - width * right1[1];
6975         vert[ 5] = org1[2] - width * right1[2];
6976         vert[ 6] = org2[0] - width * right2[0];
6977         vert[ 7] = org2[1] - width * right2[1];
6978         vert[ 8] = org2[2] - width * right2[2];
6979         vert[ 9] = org2[0] + width * right2[0];
6980         vert[10] = org2[1] + width * right2[1];
6981         vert[11] = org2[2] + width * right2[2];
6982 }
6983
6984 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)
6985 {
6986         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6987         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6988         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6989         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6990         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6991         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
6992         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
6993         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
6994         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
6995         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
6996         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
6997         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
6998 }
6999
7000 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7001 {
7002         int i;
7003         float *vertex3f;
7004         float v[3];
7005         VectorSet(v, x, y, z);
7006         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7007                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7008                         break;
7009         if (i == mesh->numvertices)
7010         {
7011                 if (mesh->numvertices < mesh->maxvertices)
7012                 {
7013                         VectorCopy(v, vertex3f);
7014                         mesh->numvertices++;
7015                 }
7016                 return mesh->numvertices;
7017         }
7018         else
7019                 return i;
7020 }
7021
7022 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7023 {
7024         int i;
7025         int *e, element[3];
7026         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7027         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7028         e = mesh->element3i + mesh->numtriangles * 3;
7029         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7030         {
7031                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7032                 if (mesh->numtriangles < mesh->maxtriangles)
7033                 {
7034                         *e++ = element[0];
7035                         *e++ = element[1];
7036                         *e++ = element[2];
7037                         mesh->numtriangles++;
7038                 }
7039                 element[1] = element[2];
7040         }
7041 }
7042
7043 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7044 {
7045         int i;
7046         int *e, element[3];
7047         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7048         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7049         e = mesh->element3i + mesh->numtriangles * 3;
7050         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7051         {
7052                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7053                 if (mesh->numtriangles < mesh->maxtriangles)
7054                 {
7055                         *e++ = element[0];
7056                         *e++ = element[1];
7057                         *e++ = element[2];
7058                         mesh->numtriangles++;
7059                 }
7060                 element[1] = element[2];
7061         }
7062 }
7063
7064 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7065 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7066 {
7067         int planenum, planenum2;
7068         int w;
7069         int tempnumpoints;
7070         mplane_t *plane, *plane2;
7071         double maxdist;
7072         double temppoints[2][256*3];
7073         // figure out how large a bounding box we need to properly compute this brush
7074         maxdist = 0;
7075         for (w = 0;w < numplanes;w++)
7076                 maxdist = max(maxdist, fabs(planes[w].dist));
7077         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7078         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7079         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7080         {
7081                 w = 0;
7082                 tempnumpoints = 4;
7083                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7084                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7085                 {
7086                         if (planenum2 == planenum)
7087                                 continue;
7088                         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);
7089                         w = !w;
7090                 }
7091                 if (tempnumpoints < 3)
7092                         continue;
7093                 // generate elements forming a triangle fan for this polygon
7094                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7095         }
7096 }
7097
7098 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)
7099 {
7100         texturelayer_t *layer;
7101         layer = t->currentlayers + t->currentnumlayers++;
7102         layer->type = type;
7103         layer->depthmask = depthmask;
7104         layer->blendfunc1 = blendfunc1;
7105         layer->blendfunc2 = blendfunc2;
7106         layer->texture = texture;
7107         layer->texmatrix = *matrix;
7108         layer->color[0] = r;
7109         layer->color[1] = g;
7110         layer->color[2] = b;
7111         layer->color[3] = a;
7112 }
7113
7114 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7115 {
7116         if(parms[0] == 0 && parms[1] == 0)
7117                 return false;
7118         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7119                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7120                         return false;
7121         return true;
7122 }
7123
7124 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7125 {
7126         double index, f;
7127         index = parms[2] + r_refdef.scene.time * parms[3];
7128         index -= floor(index);
7129         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7130         {
7131         default:
7132         case Q3WAVEFUNC_NONE:
7133         case Q3WAVEFUNC_NOISE:
7134         case Q3WAVEFUNC_COUNT:
7135                 f = 0;
7136                 break;
7137         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7138         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7139         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7140         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7141         case Q3WAVEFUNC_TRIANGLE:
7142                 index *= 4;
7143                 f = index - floor(index);
7144                 if (index < 1)
7145                         f = f;
7146                 else if (index < 2)
7147                         f = 1 - f;
7148                 else if (index < 3)
7149                         f = -f;
7150                 else
7151                         f = -(1 - f);
7152                 break;
7153         }
7154         f = parms[0] + parms[1] * f;
7155         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7156                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7157         return (float) f;
7158 }
7159
7160 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7161 {
7162         int w, h, idx;
7163         float f;
7164         float tcmat[12];
7165         matrix4x4_t matrix, temp;
7166         switch(tcmod->tcmod)
7167         {
7168                 case Q3TCMOD_COUNT:
7169                 case Q3TCMOD_NONE:
7170                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7171                                 matrix = r_waterscrollmatrix;
7172                         else
7173                                 matrix = identitymatrix;
7174                         break;
7175                 case Q3TCMOD_ENTITYTRANSLATE:
7176                         // this is used in Q3 to allow the gamecode to control texcoord
7177                         // scrolling on the entity, which is not supported in darkplaces yet.
7178                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7179                         break;
7180                 case Q3TCMOD_ROTATE:
7181                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7182                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7183                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7184                         break;
7185                 case Q3TCMOD_SCALE:
7186                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7187                         break;
7188                 case Q3TCMOD_SCROLL:
7189                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7190                         break;
7191                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7192                         w = (int) tcmod->parms[0];
7193                         h = (int) tcmod->parms[1];
7194                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7195                         f = f - floor(f);
7196                         idx = (int) floor(f * w * h);
7197                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7198                         break;
7199                 case Q3TCMOD_STRETCH:
7200                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7201                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7202                         break;
7203                 case Q3TCMOD_TRANSFORM:
7204                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7205                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7206                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7207                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7208                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7209                         break;
7210                 case Q3TCMOD_TURBULENT:
7211                         // this is handled in the RSurf_PrepareVertices function
7212                         matrix = identitymatrix;
7213                         break;
7214         }
7215         temp = *texmatrix;
7216         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7217 }
7218
7219 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7220 {
7221         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7222         char name[MAX_QPATH];
7223         skinframe_t *skinframe;
7224         unsigned char pixels[296*194];
7225         strlcpy(cache->name, skinname, sizeof(cache->name));
7226         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7227         if (developer_loading.integer)
7228                 Con_Printf("loading %s\n", name);
7229         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7230         if (!skinframe || !skinframe->base)
7231         {
7232                 unsigned char *f;
7233                 fs_offset_t filesize;
7234                 skinframe = NULL;
7235                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7236                 if (f)
7237                 {
7238                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7239                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7240                         Mem_Free(f);
7241                 }
7242         }
7243         cache->skinframe = skinframe;
7244 }
7245
7246 texture_t *R_GetCurrentTexture(texture_t *t)
7247 {
7248         int i;
7249         const entity_render_t *ent = rsurface.entity;
7250         dp_model_t *model = ent->model;
7251         q3shaderinfo_layer_tcmod_t *tcmod;
7252
7253         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7254                 return t->currentframe;
7255         t->update_lastrenderframe = r_textureframe;
7256         t->update_lastrenderentity = (void *)ent;
7257
7258         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7259                 t->camera_entity = ent->entitynumber;
7260         else
7261                 t->camera_entity = 0;
7262
7263         // switch to an alternate material if this is a q1bsp animated material
7264         {
7265                 texture_t *texture = t;
7266                 int s = rsurface.ent_skinnum;
7267                 if ((unsigned int)s >= (unsigned int)model->numskins)
7268                         s = 0;
7269                 if (model->skinscenes)
7270                 {
7271                         if (model->skinscenes[s].framecount > 1)
7272                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7273                         else
7274                                 s = model->skinscenes[s].firstframe;
7275                 }
7276                 if (s > 0)
7277                         t = t + s * model->num_surfaces;
7278                 if (t->animated)
7279                 {
7280                         // use an alternate animation if the entity's frame is not 0,
7281                         // and only if the texture has an alternate animation
7282                         if (rsurface.ent_alttextures && t->anim_total[1])
7283                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7284                         else
7285                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7286                 }
7287                 texture->currentframe = t;
7288         }
7289
7290         // update currentskinframe to be a qw skin or animation frame
7291         if (rsurface.ent_qwskin >= 0)
7292         {
7293                 i = rsurface.ent_qwskin;
7294                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7295                 {
7296                         r_qwskincache_size = cl.maxclients;
7297                         if (r_qwskincache)
7298                                 Mem_Free(r_qwskincache);
7299                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7300                 }
7301                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7302                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7303                 t->currentskinframe = r_qwskincache[i].skinframe;
7304                 if (t->currentskinframe == NULL)
7305                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7306         }
7307         else if (t->numskinframes >= 2)
7308                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7309         if (t->backgroundnumskinframes >= 2)
7310                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7311
7312         t->currentmaterialflags = t->basematerialflags;
7313         t->currentalpha = rsurface.colormod[3];
7314         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7315                 t->currentalpha *= r_wateralpha.value;
7316         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7317                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7318         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7319                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7320         if (!(rsurface.ent_flags & RENDER_LIGHT))
7321                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7322         else if (FAKELIGHT_ENABLED)
7323         {
7324                         // no modellight if using fakelight for the map
7325         }
7326         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7327         {
7328                 // pick a model lighting mode
7329                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7330                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7331                 else
7332                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7333         }
7334         if (rsurface.ent_flags & RENDER_ADDITIVE)
7335                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7336         else if (t->currentalpha < 1)
7337                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7338         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7339                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7340         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7341                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7342         if (t->backgroundnumskinframes)
7343                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7344         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7345         {
7346                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7347                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7348         }
7349         else
7350                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7351         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7352                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7353
7354         // there is no tcmod
7355         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7356         {
7357                 t->currenttexmatrix = r_waterscrollmatrix;
7358                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7359         }
7360         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7361         {
7362                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7363                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7364         }
7365
7366         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7367                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7368         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7369                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7370
7371         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7372         if (t->currentskinframe->qpixels)
7373                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7374         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7375         if (!t->basetexture)
7376                 t->basetexture = r_texture_notexture;
7377         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7378         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7379         t->nmaptexture = t->currentskinframe->nmap;
7380         if (!t->nmaptexture)
7381                 t->nmaptexture = r_texture_blanknormalmap;
7382         t->glosstexture = r_texture_black;
7383         t->glowtexture = t->currentskinframe->glow;
7384         t->fogtexture = t->currentskinframe->fog;
7385         t->reflectmasktexture = t->currentskinframe->reflect;
7386         if (t->backgroundnumskinframes)
7387         {
7388                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7389                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7390                 t->backgroundglosstexture = r_texture_black;
7391                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7392                 if (!t->backgroundnmaptexture)
7393                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7394         }
7395         else
7396         {
7397                 t->backgroundbasetexture = r_texture_white;
7398                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7399                 t->backgroundglosstexture = r_texture_black;
7400                 t->backgroundglowtexture = NULL;
7401         }
7402         t->specularpower = r_shadow_glossexponent.value;
7403         // TODO: store reference values for these in the texture?
7404         t->specularscale = 0;
7405         if (r_shadow_gloss.integer > 0)
7406         {
7407                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7408                 {
7409                         if (r_shadow_glossintensity.value > 0)
7410                         {
7411                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7412                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7413                                 t->specularscale = r_shadow_glossintensity.value;
7414                         }
7415                 }
7416                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7417                 {
7418                         t->glosstexture = r_texture_white;
7419                         t->backgroundglosstexture = r_texture_white;
7420                         t->specularscale = r_shadow_gloss2intensity.value;
7421                         t->specularpower = r_shadow_gloss2exponent.value;
7422                 }
7423         }
7424         t->specularscale *= t->specularscalemod;
7425         t->specularpower *= t->specularpowermod;
7426
7427         // lightmaps mode looks bad with dlights using actual texturing, so turn
7428         // off the colormap and glossmap, but leave the normalmap on as it still
7429         // accurately represents the shading involved
7430         if (gl_lightmaps.integer)
7431         {
7432                 t->basetexture = r_texture_grey128;
7433                 t->pantstexture = r_texture_black;
7434                 t->shirttexture = r_texture_black;
7435                 t->nmaptexture = r_texture_blanknormalmap;
7436                 t->glosstexture = r_texture_black;
7437                 t->glowtexture = NULL;
7438                 t->fogtexture = NULL;
7439                 t->reflectmasktexture = NULL;
7440                 t->backgroundbasetexture = NULL;
7441                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7442                 t->backgroundglosstexture = r_texture_black;
7443                 t->backgroundglowtexture = NULL;
7444                 t->specularscale = 0;
7445                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7446         }
7447
7448         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7449         VectorClear(t->dlightcolor);
7450         t->currentnumlayers = 0;
7451         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7452         {
7453                 int blendfunc1, blendfunc2;
7454                 qboolean depthmask;
7455                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7456                 {
7457                         blendfunc1 = GL_SRC_ALPHA;
7458                         blendfunc2 = GL_ONE;
7459                 }
7460                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7461                 {
7462                         blendfunc1 = GL_SRC_ALPHA;
7463                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7464                 }
7465                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7466                 {
7467                         blendfunc1 = t->customblendfunc[0];
7468                         blendfunc2 = t->customblendfunc[1];
7469                 }
7470                 else
7471                 {
7472                         blendfunc1 = GL_ONE;
7473                         blendfunc2 = GL_ZERO;
7474                 }
7475                 // don't colormod evilblend textures
7476                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7477                         VectorSet(t->lightmapcolor, 1, 1, 1);
7478                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7479                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7480                 {
7481                         // fullbright is not affected by r_refdef.lightmapintensity
7482                         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]);
7483                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7484                                 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]);
7485                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7486                                 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]);
7487                 }
7488                 else
7489                 {
7490                         vec3_t ambientcolor;
7491                         float colorscale;
7492                         // set the color tint used for lights affecting this surface
7493                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7494                         colorscale = 2;
7495                         // q3bsp has no lightmap updates, so the lightstylevalue that
7496                         // would normally be baked into the lightmap must be
7497                         // applied to the color
7498                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7499                         if (model->type == mod_brushq3)
7500                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7501                         colorscale *= r_refdef.lightmapintensity;
7502                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7503                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7504                         // basic lit geometry
7505                         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]);
7506                         // add pants/shirt if needed
7507                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7508                                 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]);
7509                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7510                                 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]);
7511                         // now add ambient passes if needed
7512                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7513                         {
7514                                 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]);
7515                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7516                                         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]);
7517                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7518                                         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]);
7519                         }
7520                 }
7521                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7522                         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]);
7523                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7524                 {
7525                         // if this is opaque use alpha blend which will darken the earlier
7526                         // passes cheaply.
7527                         //
7528                         // if this is an alpha blended material, all the earlier passes
7529                         // were darkened by fog already, so we only need to add the fog
7530                         // color ontop through the fog mask texture
7531                         //
7532                         // if this is an additive blended material, all the earlier passes
7533                         // were darkened by fog already, and we should not add fog color
7534                         // (because the background was not darkened, there is no fog color
7535                         // that was lost behind it).
7536                         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]);
7537                 }
7538         }
7539
7540         return t->currentframe;
7541 }
7542
7543 rsurfacestate_t rsurface;
7544
7545 void RSurf_ActiveWorldEntity(void)
7546 {
7547         dp_model_t *model = r_refdef.scene.worldmodel;
7548         //if (rsurface.entity == r_refdef.scene.worldentity)
7549         //      return;
7550         rsurface.entity = r_refdef.scene.worldentity;
7551         rsurface.skeleton = NULL;
7552         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7553         rsurface.ent_skinnum = 0;
7554         rsurface.ent_qwskin = -1;
7555         rsurface.ent_shadertime = 0;
7556         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7557         rsurface.matrix = identitymatrix;
7558         rsurface.inversematrix = identitymatrix;
7559         rsurface.matrixscale = 1;
7560         rsurface.inversematrixscale = 1;
7561         R_EntityMatrix(&identitymatrix);
7562         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7563         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7564         rsurface.fograngerecip = r_refdef.fograngerecip;
7565         rsurface.fogheightfade = r_refdef.fogheightfade;
7566         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7567         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7568         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7569         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7570         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7571         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7572         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7573         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7574         rsurface.colormod[3] = 1;
7575         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);
7576         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7577         rsurface.frameblend[0].lerp = 1;
7578         rsurface.ent_alttextures = false;
7579         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7580         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7581         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7582         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7583         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7584         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7585         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7586         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7587         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7588         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7589         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7590         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7591         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7592         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7593         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7594         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7595         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7596         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7597         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7598         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7599         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7600         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7601         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7602         rsurface.modelelement3i = model->surfmesh.data_element3i;
7603         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7604         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7605         rsurface.modelelement3s = model->surfmesh.data_element3s;
7606         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7607         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7608         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7609         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7610         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7611         rsurface.modelsurfaces = model->data_surfaces;
7612         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7613         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7614         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7615         rsurface.modelgeneratedvertex = false;
7616         rsurface.batchgeneratedvertex = false;
7617         rsurface.batchfirstvertex = 0;
7618         rsurface.batchnumvertices = 0;
7619         rsurface.batchfirsttriangle = 0;
7620         rsurface.batchnumtriangles = 0;
7621         rsurface.batchvertex3f  = NULL;
7622         rsurface.batchvertex3f_vertexbuffer = NULL;
7623         rsurface.batchvertex3f_bufferoffset = 0;
7624         rsurface.batchsvector3f = NULL;
7625         rsurface.batchsvector3f_vertexbuffer = NULL;
7626         rsurface.batchsvector3f_bufferoffset = 0;
7627         rsurface.batchtvector3f = NULL;
7628         rsurface.batchtvector3f_vertexbuffer = NULL;
7629         rsurface.batchtvector3f_bufferoffset = 0;
7630         rsurface.batchnormal3f  = NULL;
7631         rsurface.batchnormal3f_vertexbuffer = NULL;
7632         rsurface.batchnormal3f_bufferoffset = 0;
7633         rsurface.batchlightmapcolor4f = NULL;
7634         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7635         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7636         rsurface.batchtexcoordtexture2f = NULL;
7637         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7638         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7639         rsurface.batchtexcoordlightmap2f = NULL;
7640         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7641         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7642         rsurface.batchvertexmesh = NULL;
7643         rsurface.batchvertexmeshbuffer = NULL;
7644         rsurface.batchvertex3fbuffer = NULL;
7645         rsurface.batchelement3i = NULL;
7646         rsurface.batchelement3i_indexbuffer = NULL;
7647         rsurface.batchelement3i_bufferoffset = 0;
7648         rsurface.batchelement3s = NULL;
7649         rsurface.batchelement3s_indexbuffer = NULL;
7650         rsurface.batchelement3s_bufferoffset = 0;
7651         rsurface.passcolor4f = NULL;
7652         rsurface.passcolor4f_vertexbuffer = NULL;
7653         rsurface.passcolor4f_bufferoffset = 0;
7654 }
7655
7656 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7657 {
7658         dp_model_t *model = ent->model;
7659         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7660         //      return;
7661         rsurface.entity = (entity_render_t *)ent;
7662         rsurface.skeleton = ent->skeleton;
7663         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7664         rsurface.ent_skinnum = ent->skinnum;
7665         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;
7666         rsurface.ent_shadertime = ent->shadertime;
7667         rsurface.ent_flags = ent->flags;
7668         rsurface.matrix = ent->matrix;
7669         rsurface.inversematrix = ent->inversematrix;
7670         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7671         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7672         R_EntityMatrix(&rsurface.matrix);
7673         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7674         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7675         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7676         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7677         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7678         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7679         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7680         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7681         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7682         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7683         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7684         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7685         rsurface.colormod[3] = ent->alpha;
7686         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7687         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7688         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7689         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7690         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7691         if (ent->model->brush.submodel && !prepass)
7692         {
7693                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7694                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7695         }
7696         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7697         {
7698                 if (ent->animcache_vertex3f)
7699                 {
7700                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7701                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7702                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7703                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7704                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7705                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7706                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7707                 }
7708                 else if (wanttangents)
7709                 {
7710                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7711                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7712                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7713                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7714                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7715                         rsurface.modelvertexmesh = NULL;
7716                         rsurface.modelvertexmeshbuffer = NULL;
7717                         rsurface.modelvertex3fbuffer = NULL;
7718                 }
7719                 else if (wantnormals)
7720                 {
7721                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7722                         rsurface.modelsvector3f = NULL;
7723                         rsurface.modeltvector3f = NULL;
7724                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7725                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7726                         rsurface.modelvertexmesh = NULL;
7727                         rsurface.modelvertexmeshbuffer = NULL;
7728                         rsurface.modelvertex3fbuffer = NULL;
7729                 }
7730                 else
7731                 {
7732                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7733                         rsurface.modelsvector3f = NULL;
7734                         rsurface.modeltvector3f = NULL;
7735                         rsurface.modelnormal3f = NULL;
7736                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7737                         rsurface.modelvertexmesh = NULL;
7738                         rsurface.modelvertexmeshbuffer = NULL;
7739                         rsurface.modelvertex3fbuffer = NULL;
7740                 }
7741                 rsurface.modelvertex3f_vertexbuffer = 0;
7742                 rsurface.modelvertex3f_bufferoffset = 0;
7743                 rsurface.modelsvector3f_vertexbuffer = 0;
7744                 rsurface.modelsvector3f_bufferoffset = 0;
7745                 rsurface.modeltvector3f_vertexbuffer = 0;
7746                 rsurface.modeltvector3f_bufferoffset = 0;
7747                 rsurface.modelnormal3f_vertexbuffer = 0;
7748                 rsurface.modelnormal3f_bufferoffset = 0;
7749                 rsurface.modelgeneratedvertex = true;
7750         }
7751         else
7752         {
7753                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7754                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7755                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7756                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7757                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7758                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7759                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7760                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7761                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7762                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7763                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7765                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7766                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7767                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7768                 rsurface.modelgeneratedvertex = false;
7769         }
7770         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7771         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7772         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7773         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7774         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7775         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7776         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7777         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7778         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7779         rsurface.modelelement3i = model->surfmesh.data_element3i;
7780         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7781         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7782         rsurface.modelelement3s = model->surfmesh.data_element3s;
7783         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7784         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7785         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7786         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7787         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7788         rsurface.modelsurfaces = model->data_surfaces;
7789         rsurface.batchgeneratedvertex = false;
7790         rsurface.batchfirstvertex = 0;
7791         rsurface.batchnumvertices = 0;
7792         rsurface.batchfirsttriangle = 0;
7793         rsurface.batchnumtriangles = 0;
7794         rsurface.batchvertex3f  = NULL;
7795         rsurface.batchvertex3f_vertexbuffer = NULL;
7796         rsurface.batchvertex3f_bufferoffset = 0;
7797         rsurface.batchsvector3f = NULL;
7798         rsurface.batchsvector3f_vertexbuffer = NULL;
7799         rsurface.batchsvector3f_bufferoffset = 0;
7800         rsurface.batchtvector3f = NULL;
7801         rsurface.batchtvector3f_vertexbuffer = NULL;
7802         rsurface.batchtvector3f_bufferoffset = 0;
7803         rsurface.batchnormal3f  = NULL;
7804         rsurface.batchnormal3f_vertexbuffer = NULL;
7805         rsurface.batchnormal3f_bufferoffset = 0;
7806         rsurface.batchlightmapcolor4f = NULL;
7807         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7808         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7809         rsurface.batchtexcoordtexture2f = NULL;
7810         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7811         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7812         rsurface.batchtexcoordlightmap2f = NULL;
7813         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7814         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7815         rsurface.batchvertexmesh = NULL;
7816         rsurface.batchvertexmeshbuffer = NULL;
7817         rsurface.batchvertex3fbuffer = NULL;
7818         rsurface.batchelement3i = NULL;
7819         rsurface.batchelement3i_indexbuffer = NULL;
7820         rsurface.batchelement3i_bufferoffset = 0;
7821         rsurface.batchelement3s = NULL;
7822         rsurface.batchelement3s_indexbuffer = NULL;
7823         rsurface.batchelement3s_bufferoffset = 0;
7824         rsurface.passcolor4f = NULL;
7825         rsurface.passcolor4f_vertexbuffer = NULL;
7826         rsurface.passcolor4f_bufferoffset = 0;
7827 }
7828
7829 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)
7830 {
7831         rsurface.entity = r_refdef.scene.worldentity;
7832         rsurface.skeleton = NULL;
7833         rsurface.ent_skinnum = 0;
7834         rsurface.ent_qwskin = -1;
7835         rsurface.ent_shadertime = shadertime;
7836         rsurface.ent_flags = entflags;
7837         rsurface.modelnumvertices = numvertices;
7838         rsurface.modelnumtriangles = numtriangles;
7839         rsurface.matrix = *matrix;
7840         rsurface.inversematrix = *inversematrix;
7841         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7842         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7843         R_EntityMatrix(&rsurface.matrix);
7844         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7845         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7846         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7847         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7848         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7849         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7850         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7851         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7852         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7853         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7854         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7855         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7856         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);
7857         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7858         rsurface.frameblend[0].lerp = 1;
7859         rsurface.ent_alttextures = false;
7860         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7861         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7862         if (wanttangents)
7863         {
7864                 rsurface.modelvertex3f = (float *)vertex3f;
7865                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7866                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7867                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7868         }
7869         else if (wantnormals)
7870         {
7871                 rsurface.modelvertex3f = (float *)vertex3f;
7872                 rsurface.modelsvector3f = NULL;
7873                 rsurface.modeltvector3f = NULL;
7874                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7875         }
7876         else
7877         {
7878                 rsurface.modelvertex3f = (float *)vertex3f;
7879                 rsurface.modelsvector3f = NULL;
7880                 rsurface.modeltvector3f = NULL;
7881                 rsurface.modelnormal3f = NULL;
7882         }
7883         rsurface.modelvertexmesh = NULL;
7884         rsurface.modelvertexmeshbuffer = NULL;
7885         rsurface.modelvertex3fbuffer = NULL;
7886         rsurface.modelvertex3f_vertexbuffer = 0;
7887         rsurface.modelvertex3f_bufferoffset = 0;
7888         rsurface.modelsvector3f_vertexbuffer = 0;
7889         rsurface.modelsvector3f_bufferoffset = 0;
7890         rsurface.modeltvector3f_vertexbuffer = 0;
7891         rsurface.modeltvector3f_bufferoffset = 0;
7892         rsurface.modelnormal3f_vertexbuffer = 0;
7893         rsurface.modelnormal3f_bufferoffset = 0;
7894         rsurface.modelgeneratedvertex = true;
7895         rsurface.modellightmapcolor4f  = (float *)color4f;
7896         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7897         rsurface.modellightmapcolor4f_bufferoffset = 0;
7898         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7899         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7900         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7901         rsurface.modeltexcoordlightmap2f  = NULL;
7902         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7903         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7904         rsurface.modelelement3i = (int *)element3i;
7905         rsurface.modelelement3i_indexbuffer = NULL;
7906         rsurface.modelelement3i_bufferoffset = 0;
7907         rsurface.modelelement3s = (unsigned short *)element3s;
7908         rsurface.modelelement3s_indexbuffer = NULL;
7909         rsurface.modelelement3s_bufferoffset = 0;
7910         rsurface.modellightmapoffsets = NULL;
7911         rsurface.modelsurfaces = NULL;
7912         rsurface.batchgeneratedvertex = false;
7913         rsurface.batchfirstvertex = 0;
7914         rsurface.batchnumvertices = 0;
7915         rsurface.batchfirsttriangle = 0;
7916         rsurface.batchnumtriangles = 0;
7917         rsurface.batchvertex3f  = NULL;
7918         rsurface.batchvertex3f_vertexbuffer = NULL;
7919         rsurface.batchvertex3f_bufferoffset = 0;
7920         rsurface.batchsvector3f = NULL;
7921         rsurface.batchsvector3f_vertexbuffer = NULL;
7922         rsurface.batchsvector3f_bufferoffset = 0;
7923         rsurface.batchtvector3f = NULL;
7924         rsurface.batchtvector3f_vertexbuffer = NULL;
7925         rsurface.batchtvector3f_bufferoffset = 0;
7926         rsurface.batchnormal3f  = NULL;
7927         rsurface.batchnormal3f_vertexbuffer = NULL;
7928         rsurface.batchnormal3f_bufferoffset = 0;
7929         rsurface.batchlightmapcolor4f = NULL;
7930         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7931         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7932         rsurface.batchtexcoordtexture2f = NULL;
7933         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7934         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7935         rsurface.batchtexcoordlightmap2f = NULL;
7936         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7937         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7938         rsurface.batchvertexmesh = NULL;
7939         rsurface.batchvertexmeshbuffer = NULL;
7940         rsurface.batchvertex3fbuffer = NULL;
7941         rsurface.batchelement3i = NULL;
7942         rsurface.batchelement3i_indexbuffer = NULL;
7943         rsurface.batchelement3i_bufferoffset = 0;
7944         rsurface.batchelement3s = NULL;
7945         rsurface.batchelement3s_indexbuffer = NULL;
7946         rsurface.batchelement3s_bufferoffset = 0;
7947         rsurface.passcolor4f = NULL;
7948         rsurface.passcolor4f_vertexbuffer = NULL;
7949         rsurface.passcolor4f_bufferoffset = 0;
7950
7951         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7952         {
7953                 if ((wantnormals || wanttangents) && !normal3f)
7954                 {
7955                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7956                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7957                 }
7958                 if (wanttangents && !svector3f)
7959                 {
7960                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7961                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7962                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7963                 }
7964         }
7965 }
7966
7967 float RSurf_FogPoint(const float *v)
7968 {
7969         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7970         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7971         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7972         float FogHeightFade = r_refdef.fogheightfade;
7973         float fogfrac;
7974         unsigned int fogmasktableindex;
7975         if (r_refdef.fogplaneviewabove)
7976                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7977         else
7978                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7979         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7980         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7981 }
7982
7983 float RSurf_FogVertex(const float *v)
7984 {
7985         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7986         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7987         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7988         float FogHeightFade = rsurface.fogheightfade;
7989         float fogfrac;
7990         unsigned int fogmasktableindex;
7991         if (r_refdef.fogplaneviewabove)
7992                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7993         else
7994                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7995         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
7996         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7997 }
7998
7999 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8000 {
8001         int i;
8002         for (i = 0;i < numelements;i++)
8003                 outelement3i[i] = inelement3i[i] + adjust;
8004 }
8005
8006 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8007 extern cvar_t gl_vbo;
8008 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8009 {
8010         int deformindex;
8011         int firsttriangle;
8012         int numtriangles;
8013         int firstvertex;
8014         int endvertex;
8015         int numvertices;
8016         int surfacefirsttriangle;
8017         int surfacenumtriangles;
8018         int surfacefirstvertex;
8019         int surfaceendvertex;
8020         int surfacenumvertices;
8021         int batchnumvertices;
8022         int batchnumtriangles;
8023         int needsupdate;
8024         int i, j;
8025         qboolean gaps;
8026         qboolean dynamicvertex;
8027         float amplitude;
8028         float animpos;
8029         float scale;
8030         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8031         float waveparms[4];
8032         q3shaderinfo_deform_t *deform;
8033         const msurface_t *surface, *firstsurface;
8034         r_vertexmesh_t *vertexmesh;
8035         if (!texturenumsurfaces)
8036                 return;
8037         // find vertex range of this surface batch
8038         gaps = false;
8039         firstsurface = texturesurfacelist[0];
8040         firsttriangle = firstsurface->num_firsttriangle;
8041         batchnumvertices = 0;
8042         batchnumtriangles = 0;
8043         firstvertex = endvertex = firstsurface->num_firstvertex;
8044         for (i = 0;i < texturenumsurfaces;i++)
8045         {
8046                 surface = texturesurfacelist[i];
8047                 if (surface != firstsurface + i)
8048                         gaps = true;
8049                 surfacefirstvertex = surface->num_firstvertex;
8050                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8051                 surfacenumvertices = surface->num_vertices;
8052                 surfacenumtriangles = surface->num_triangles;
8053                 if (firstvertex > surfacefirstvertex)
8054                         firstvertex = surfacefirstvertex;
8055                 if (endvertex < surfaceendvertex)
8056                         endvertex = surfaceendvertex;
8057                 batchnumvertices += surfacenumvertices;
8058                 batchnumtriangles += surfacenumtriangles;
8059         }
8060
8061         // we now know the vertex range used, and if there are any gaps in it
8062         rsurface.batchfirstvertex = firstvertex;
8063         rsurface.batchnumvertices = endvertex - firstvertex;
8064         rsurface.batchfirsttriangle = firsttriangle;
8065         rsurface.batchnumtriangles = batchnumtriangles;
8066
8067         // this variable holds flags for which properties have been updated that
8068         // may require regenerating vertexmesh array...
8069         needsupdate = 0;
8070
8071         // check if any dynamic vertex processing must occur
8072         dynamicvertex = false;
8073
8074         // if there is a chance of animated vertex colors, it's a dynamic batch
8075         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8076         {
8077                 dynamicvertex = true;
8078                 batchneed |= BATCHNEED_NOGAPS;
8079                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8080         }
8081
8082         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8083         {
8084                 switch (deform->deform)
8085                 {
8086                 default:
8087                 case Q3DEFORM_PROJECTIONSHADOW:
8088                 case Q3DEFORM_TEXT0:
8089                 case Q3DEFORM_TEXT1:
8090                 case Q3DEFORM_TEXT2:
8091                 case Q3DEFORM_TEXT3:
8092                 case Q3DEFORM_TEXT4:
8093                 case Q3DEFORM_TEXT5:
8094                 case Q3DEFORM_TEXT6:
8095                 case Q3DEFORM_TEXT7:
8096                 case Q3DEFORM_NONE:
8097                         break;
8098                 case Q3DEFORM_AUTOSPRITE:
8099                         dynamicvertex = true;
8100                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8101                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8102                         break;
8103                 case Q3DEFORM_AUTOSPRITE2:
8104                         dynamicvertex = true;
8105                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8106                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8107                         break;
8108                 case Q3DEFORM_NORMAL:
8109                         dynamicvertex = true;
8110                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8111                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8112                         break;
8113                 case Q3DEFORM_WAVE:
8114                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8115                                 break; // if wavefunc is a nop, ignore this transform
8116                         dynamicvertex = true;
8117                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8118                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8119                         break;
8120                 case Q3DEFORM_BULGE:
8121                         dynamicvertex = true;
8122                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8123                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8124                         break;
8125                 case Q3DEFORM_MOVE:
8126                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8127                                 break; // if wavefunc is a nop, ignore this transform
8128                         dynamicvertex = true;
8129                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8130                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8131                         break;
8132                 }
8133         }
8134         switch(rsurface.texture->tcgen.tcgen)
8135         {
8136         default:
8137         case Q3TCGEN_TEXTURE:
8138                 break;
8139         case Q3TCGEN_LIGHTMAP:
8140                 dynamicvertex = true;
8141                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8142                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8143                 break;
8144         case Q3TCGEN_VECTOR:
8145                 dynamicvertex = true;
8146                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8147                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8148                 break;
8149         case Q3TCGEN_ENVIRONMENT:
8150                 dynamicvertex = true;
8151                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8152                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8153                 break;
8154         }
8155         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8156         {
8157                 dynamicvertex = true;
8158                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8159                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8160         }
8161
8162         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8163         {
8164                 dynamicvertex = true;
8165                 batchneed |= BATCHNEED_NOGAPS;
8166                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8167         }
8168
8169         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8170         {
8171                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8172                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8173                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8174                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8175                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8176                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8177                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8178         }
8179
8180         // when the model data has no vertex buffer (dynamic mesh), we need to
8181         // eliminate gaps
8182         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8183                 batchneed |= BATCHNEED_NOGAPS;
8184
8185         // if needsupdate, we have to do a dynamic vertex batch for sure
8186         if (needsupdate & batchneed)
8187                 dynamicvertex = true;
8188
8189         // see if we need to build vertexmesh from arrays
8190         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8191                 dynamicvertex = true;
8192
8193         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8194         // also some drivers strongly dislike firstvertex
8195         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8196                 dynamicvertex = true;
8197
8198         rsurface.batchvertex3f = rsurface.modelvertex3f;
8199         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8200         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8201         rsurface.batchsvector3f = rsurface.modelsvector3f;
8202         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8203         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8204         rsurface.batchtvector3f = rsurface.modeltvector3f;
8205         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8206         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8207         rsurface.batchnormal3f = rsurface.modelnormal3f;
8208         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8209         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8210         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8211         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8212         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8213         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8214         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8215         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8216         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8217         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8218         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8219         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8220         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8221         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8222         rsurface.batchelement3i = rsurface.modelelement3i;
8223         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8224         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8225         rsurface.batchelement3s = rsurface.modelelement3s;
8226         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8227         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8228
8229         // if any dynamic vertex processing has to occur in software, we copy the
8230         // entire surface list together before processing to rebase the vertices
8231         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8232         //
8233         // if any gaps exist and we do not have a static vertex buffer, we have to
8234         // copy the surface list together to avoid wasting upload bandwidth on the
8235         // vertices in the gaps.
8236         //
8237         // if gaps exist and we have a static vertex buffer, we still have to
8238         // combine the index buffer ranges into one dynamic index buffer.
8239         //
8240         // in all cases we end up with data that can be drawn in one call.
8241
8242         if (!dynamicvertex)
8243         {
8244                 // static vertex data, just set pointers...
8245                 rsurface.batchgeneratedvertex = false;
8246                 // if there are gaps, we want to build a combined index buffer,
8247                 // otherwise use the original static buffer with an appropriate offset
8248                 if (gaps)
8249                 {
8250                         // build a new triangle elements array for this batch
8251                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8252                         rsurface.batchfirsttriangle = 0;
8253                         numtriangles = 0;
8254                         for (i = 0;i < texturenumsurfaces;i++)
8255                         {
8256                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8257                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8258                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8259                                 numtriangles += surfacenumtriangles;
8260                         }
8261                         rsurface.batchelement3i_indexbuffer = NULL;
8262                         rsurface.batchelement3i_bufferoffset = 0;
8263                         rsurface.batchelement3s = NULL;
8264                         rsurface.batchelement3s_indexbuffer = NULL;
8265                         rsurface.batchelement3s_bufferoffset = 0;
8266                         if (endvertex <= 65536)
8267                         {
8268                                 // make a 16bit (unsigned short) index array if possible
8269                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8270                                 for (i = 0;i < numtriangles*3;i++)
8271                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8272                         }
8273                 }
8274                 return;
8275         }
8276
8277         // something needs software processing, do it for real...
8278         // we only directly handle separate array data in this case and then
8279         // generate interleaved data if needed...
8280         rsurface.batchgeneratedvertex = true;
8281
8282         // now copy the vertex data into a combined array and make an index array
8283         // (this is what Quake3 does all the time)
8284         //if (gaps || rsurface.batchfirstvertex)
8285         {
8286                 rsurface.batchvertex3fbuffer = NULL;
8287                 rsurface.batchvertexmesh = NULL;
8288                 rsurface.batchvertexmeshbuffer = NULL;
8289                 rsurface.batchvertex3f = NULL;
8290                 rsurface.batchvertex3f_vertexbuffer = NULL;
8291                 rsurface.batchvertex3f_bufferoffset = 0;
8292                 rsurface.batchsvector3f = NULL;
8293                 rsurface.batchsvector3f_vertexbuffer = NULL;
8294                 rsurface.batchsvector3f_bufferoffset = 0;
8295                 rsurface.batchtvector3f = NULL;
8296                 rsurface.batchtvector3f_vertexbuffer = NULL;
8297                 rsurface.batchtvector3f_bufferoffset = 0;
8298                 rsurface.batchnormal3f = NULL;
8299                 rsurface.batchnormal3f_vertexbuffer = NULL;
8300                 rsurface.batchnormal3f_bufferoffset = 0;
8301                 rsurface.batchlightmapcolor4f = NULL;
8302                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8303                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8304                 rsurface.batchtexcoordtexture2f = NULL;
8305                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8306                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8307                 rsurface.batchtexcoordlightmap2f = NULL;
8308                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8309                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8310                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8311                 rsurface.batchelement3i_indexbuffer = NULL;
8312                 rsurface.batchelement3i_bufferoffset = 0;
8313                 rsurface.batchelement3s = NULL;
8314                 rsurface.batchelement3s_indexbuffer = NULL;
8315                 rsurface.batchelement3s_bufferoffset = 0;
8316                 // we'll only be setting up certain arrays as needed
8317                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8318                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8319                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8320                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8321                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8322                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8323                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8324                 {
8325                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8326                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8327                 }
8328                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8329                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8330                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8331                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8332                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8333                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8334                 numvertices = 0;
8335                 numtriangles = 0;
8336                 for (i = 0;i < texturenumsurfaces;i++)
8337                 {
8338                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8339                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8340                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8341                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8342                         // copy only the data requested
8343                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8344                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8345                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8346                         {
8347                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8348                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8349                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8350                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8351                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8352                                 {
8353                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8354                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8355                                 }
8356                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8357                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8358                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8359                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8360                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8361                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8362                         }
8363                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8364                         numvertices += surfacenumvertices;
8365                         numtriangles += surfacenumtriangles;
8366                 }
8367
8368                 // generate a 16bit index array as well if possible
8369                 // (in general, dynamic batches fit)
8370                 if (numvertices <= 65536)
8371                 {
8372                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8373                         for (i = 0;i < numtriangles*3;i++)
8374                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8375                 }
8376
8377                 // since we've copied everything, the batch now starts at 0
8378                 rsurface.batchfirstvertex = 0;
8379                 rsurface.batchnumvertices = batchnumvertices;
8380                 rsurface.batchfirsttriangle = 0;
8381                 rsurface.batchnumtriangles = batchnumtriangles;
8382         }
8383
8384         // q1bsp surfaces rendered in vertex color mode have to have colors
8385         // calculated based on lightstyles
8386         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8387         {
8388                 // generate color arrays for the surfaces in this list
8389                 int c[4];
8390                 int scale;
8391                 int size3;
8392                 const int *offsets;
8393                 const unsigned char *lm;
8394                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8395                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8396                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8397                 numvertices = 0;
8398                 for (i = 0;i < texturenumsurfaces;i++)
8399                 {
8400                         surface = texturesurfacelist[i];
8401                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8402                         surfacenumvertices = surface->num_vertices;
8403                         if (surface->lightmapinfo->samples)
8404                         {
8405                                 for (j = 0;j < surfacenumvertices;j++)
8406                                 {
8407                                         lm = surface->lightmapinfo->samples + offsets[j];
8408                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8409                                         VectorScale(lm, scale, c);
8410                                         if (surface->lightmapinfo->styles[1] != 255)
8411                                         {
8412                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8413                                                 lm += size3;
8414                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8415                                                 VectorMA(c, scale, lm, c);
8416                                                 if (surface->lightmapinfo->styles[2] != 255)
8417                                                 {
8418                                                         lm += size3;
8419                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8420                                                         VectorMA(c, scale, lm, c);
8421                                                         if (surface->lightmapinfo->styles[3] != 255)
8422                                                         {
8423                                                                 lm += size3;
8424                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8425                                                                 VectorMA(c, scale, lm, c);
8426                                                         }
8427                                                 }
8428                                         }
8429                                         c[0] >>= 7;
8430                                         c[1] >>= 7;
8431                                         c[2] >>= 7;
8432                                         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);
8433                                         numvertices++;
8434                                 }
8435                         }
8436                         else
8437                         {
8438                                 for (j = 0;j < surfacenumvertices;j++)
8439                                 {
8440                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8441                                         numvertices++;
8442                                 }
8443                         }
8444                 }
8445         }
8446
8447         // if vertices are deformed (sprite flares and things in maps, possibly
8448         // water waves, bulges and other deformations), modify the copied vertices
8449         // in place
8450         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8451         {
8452                 switch (deform->deform)
8453                 {
8454                 default:
8455                 case Q3DEFORM_PROJECTIONSHADOW:
8456                 case Q3DEFORM_TEXT0:
8457                 case Q3DEFORM_TEXT1:
8458                 case Q3DEFORM_TEXT2:
8459                 case Q3DEFORM_TEXT3:
8460                 case Q3DEFORM_TEXT4:
8461                 case Q3DEFORM_TEXT5:
8462                 case Q3DEFORM_TEXT6:
8463                 case Q3DEFORM_TEXT7:
8464                 case Q3DEFORM_NONE:
8465                         break;
8466                 case Q3DEFORM_AUTOSPRITE:
8467                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8468                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8469                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8470                         VectorNormalize(newforward);
8471                         VectorNormalize(newright);
8472                         VectorNormalize(newup);
8473 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8474 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8475 //                      rsurface.batchvertex3f_bufferoffset = 0;
8476 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8477 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8478 //                      rsurface.batchsvector3f_bufferoffset = 0;
8479 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8480 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8481 //                      rsurface.batchtvector3f_bufferoffset = 0;
8482 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8483 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8484 //                      rsurface.batchnormal3f_bufferoffset = 0;
8485                         // a single autosprite surface can contain multiple sprites...
8486                         for (j = 0;j < batchnumvertices - 3;j += 4)
8487                         {
8488                                 VectorClear(center);
8489                                 for (i = 0;i < 4;i++)
8490                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8491                                 VectorScale(center, 0.25f, center);
8492                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8493                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8494                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8495                                 for (i = 0;i < 4;i++)
8496                                 {
8497                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8498                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8499                                 }
8500                         }
8501                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8502                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8503                         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);
8504                         break;
8505                 case Q3DEFORM_AUTOSPRITE2:
8506                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8507                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8508                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8509                         VectorNormalize(newforward);
8510                         VectorNormalize(newright);
8511                         VectorNormalize(newup);
8512 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8513 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8514 //                      rsurface.batchvertex3f_bufferoffset = 0;
8515                         {
8516                                 const float *v1, *v2;
8517                                 vec3_t start, end;
8518                                 float f, l;
8519                                 struct
8520                                 {
8521                                         float length2;
8522                                         const float *v1;
8523                                         const float *v2;
8524                                 }
8525                                 shortest[2];
8526                                 memset(shortest, 0, sizeof(shortest));
8527                                 // a single autosprite surface can contain multiple sprites...
8528                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8529                                 {
8530                                         VectorClear(center);
8531                                         for (i = 0;i < 4;i++)
8532                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8533                                         VectorScale(center, 0.25f, center);
8534                                         // find the two shortest edges, then use them to define the
8535                                         // axis vectors for rotating around the central axis
8536                                         for (i = 0;i < 6;i++)
8537                                         {
8538                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8539                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8540                                                 l = VectorDistance2(v1, v2);
8541                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8542                                                 if (v1[2] != v2[2])
8543                                                         l += (1.0f / 1024.0f);
8544                                                 if (shortest[0].length2 > l || i == 0)
8545                                                 {
8546                                                         shortest[1] = shortest[0];
8547                                                         shortest[0].length2 = l;
8548                                                         shortest[0].v1 = v1;
8549                                                         shortest[0].v2 = v2;
8550                                                 }
8551                                                 else if (shortest[1].length2 > l || i == 1)
8552                                                 {
8553                                                         shortest[1].length2 = l;
8554                                                         shortest[1].v1 = v1;
8555                                                         shortest[1].v2 = v2;
8556                                                 }
8557                                         }
8558                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8559                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8560                                         // this calculates the right vector from the shortest edge
8561                                         // and the up vector from the edge midpoints
8562                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8563                                         VectorNormalize(right);
8564                                         VectorSubtract(end, start, up);
8565                                         VectorNormalize(up);
8566                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8567                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8568                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8569                                         VectorNegate(forward, forward);
8570                                         VectorReflect(forward, 0, up, forward);
8571                                         VectorNormalize(forward);
8572                                         CrossProduct(up, forward, newright);
8573                                         VectorNormalize(newright);
8574                                         // rotate the quad around the up axis vector, this is made
8575                                         // especially easy by the fact we know the quad is flat,
8576                                         // so we only have to subtract the center position and
8577                                         // measure distance along the right vector, and then
8578                                         // multiply that by the newright vector and add back the
8579                                         // center position
8580                                         // we also need to subtract the old position to undo the
8581                                         // displacement from the center, which we do with a
8582                                         // DotProduct, the subtraction/addition of center is also
8583                                         // optimized into DotProducts here
8584                                         l = DotProduct(right, center);
8585                                         for (i = 0;i < 4;i++)
8586                                         {
8587                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8588                                                 f = DotProduct(right, v1) - l;
8589                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8590                                         }
8591                                 }
8592                         }
8593                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8594                         {
8595 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8596 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8597 //                              rsurface.batchnormal3f_bufferoffset = 0;
8598                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8599                         }
8600                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8601                         {
8602 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8603 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8604 //                              rsurface.batchsvector3f_bufferoffset = 0;
8605 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8606 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8607 //                              rsurface.batchtvector3f_bufferoffset = 0;
8608                                 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);
8609                         }
8610                         break;
8611                 case Q3DEFORM_NORMAL:
8612                         // deform the normals to make reflections wavey
8613                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8614                         rsurface.batchnormal3f_vertexbuffer = NULL;
8615                         rsurface.batchnormal3f_bufferoffset = 0;
8616                         for (j = 0;j < batchnumvertices;j++)
8617                         {
8618                                 float vertex[3];
8619                                 float *normal = rsurface.batchnormal3f + 3*j;
8620                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8621                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8622                                 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]);
8623                                 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]);
8624                                 VectorNormalize(normal);
8625                         }
8626                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8627                         {
8628 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8629 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8630 //                              rsurface.batchsvector3f_bufferoffset = 0;
8631 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8632 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8633 //                              rsurface.batchtvector3f_bufferoffset = 0;
8634                                 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);
8635                         }
8636                         break;
8637                 case Q3DEFORM_WAVE:
8638                         // deform vertex array to make wavey water and flags and such
8639                         waveparms[0] = deform->waveparms[0];
8640                         waveparms[1] = deform->waveparms[1];
8641                         waveparms[2] = deform->waveparms[2];
8642                         waveparms[3] = deform->waveparms[3];
8643                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8644                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8645                         // this is how a divisor of vertex influence on deformation
8646                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8647                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8648 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8649 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8650 //                      rsurface.batchvertex3f_bufferoffset = 0;
8651 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8652 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8653 //                      rsurface.batchnormal3f_bufferoffset = 0;
8654                         for (j = 0;j < batchnumvertices;j++)
8655                         {
8656                                 // if the wavefunc depends on time, evaluate it per-vertex
8657                                 if (waveparms[3])
8658                                 {
8659                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8660                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8661                                 }
8662                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8663                         }
8664                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8665                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8666                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8667                         {
8668 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8669 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8670 //                              rsurface.batchsvector3f_bufferoffset = 0;
8671 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8673 //                              rsurface.batchtvector3f_bufferoffset = 0;
8674                                 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);
8675                         }
8676                         break;
8677                 case Q3DEFORM_BULGE:
8678                         // deform vertex array to make the surface have moving bulges
8679 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8680 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8681 //                      rsurface.batchvertex3f_bufferoffset = 0;
8682 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8683 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8684 //                      rsurface.batchnormal3f_bufferoffset = 0;
8685                         for (j = 0;j < batchnumvertices;j++)
8686                         {
8687                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8688                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8689                         }
8690                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8691                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8692                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8693                         {
8694 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8695 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8696 //                              rsurface.batchsvector3f_bufferoffset = 0;
8697 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8698 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8699 //                              rsurface.batchtvector3f_bufferoffset = 0;
8700                                 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);
8701                         }
8702                         break;
8703                 case Q3DEFORM_MOVE:
8704                         // deform vertex array
8705                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8706                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8707                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8708                         VectorScale(deform->parms, scale, waveparms);
8709 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8710 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8711 //                      rsurface.batchvertex3f_bufferoffset = 0;
8712                         for (j = 0;j < batchnumvertices;j++)
8713                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8714                         break;
8715                 }
8716         }
8717
8718         // generate texcoords based on the chosen texcoord source
8719         switch(rsurface.texture->tcgen.tcgen)
8720         {
8721         default:
8722         case Q3TCGEN_TEXTURE:
8723                 break;
8724         case Q3TCGEN_LIGHTMAP:
8725 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8726 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8727 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8728                 if (rsurface.batchtexcoordlightmap2f)
8729                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8730                 break;
8731         case Q3TCGEN_VECTOR:
8732 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8733 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8734 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8735                 for (j = 0;j < batchnumvertices;j++)
8736                 {
8737                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8738                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8739                 }
8740                 break;
8741         case Q3TCGEN_ENVIRONMENT:
8742                 // make environment reflections using a spheremap
8743                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8744                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8745                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8746                 for (j = 0;j < batchnumvertices;j++)
8747                 {
8748                         // identical to Q3A's method, but executed in worldspace so
8749                         // carried models can be shiny too
8750
8751                         float viewer[3], d, reflected[3], worldreflected[3];
8752
8753                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8754                         // VectorNormalize(viewer);
8755
8756                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8757
8758                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8759                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8760                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8761                         // note: this is proportinal to viewer, so we can normalize later
8762
8763                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8764                         VectorNormalize(worldreflected);
8765
8766                         // note: this sphere map only uses world x and z!
8767                         // so positive and negative y will LOOK THE SAME.
8768                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8769                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8770                 }
8771                 break;
8772         }
8773         // the only tcmod that needs software vertex processing is turbulent, so
8774         // check for it here and apply the changes if needed
8775         // and we only support that as the first one
8776         // (handling a mixture of turbulent and other tcmods would be problematic
8777         //  without punting it entirely to a software path)
8778         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8779         {
8780                 amplitude = rsurface.texture->tcmods[0].parms[1];
8781                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8782 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8783 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8784 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8785                 for (j = 0;j < batchnumvertices;j++)
8786                 {
8787                         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);
8788                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8789                 }
8790         }
8791
8792         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8793         {
8794                 // convert the modified arrays to vertex structs
8795 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8796 //              rsurface.batchvertexmeshbuffer = NULL;
8797                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8798                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8799                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8800                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8801                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8802                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8803                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8804                 {
8805                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8806                         {
8807                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8808                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8809                         }
8810                 }
8811                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8812                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8813                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8814                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8815                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8816                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8817                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8818                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8819                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8820         }
8821 }
8822
8823 void RSurf_DrawBatch(void)
8824 {
8825         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8826         // through the pipeline, killing it earlier in the pipeline would have
8827         // per-surface overhead rather than per-batch overhead, so it's best to
8828         // reject it here, before it hits glDraw.
8829         if (rsurface.batchnumtriangles == 0)
8830                 return;
8831 #if 0
8832         // batch debugging code
8833         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8834         {
8835                 int i;
8836                 int j;
8837                 int c;
8838                 const int *e;
8839                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8840                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8841                 {
8842                         c = e[i];
8843                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8844                         {
8845                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8846                                 {
8847                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8848                                                 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);
8849                                         break;
8850                                 }
8851                         }
8852                 }
8853         }
8854 #endif
8855         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);
8856 }
8857
8858 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8859 {
8860         // pick the closest matching water plane
8861         int planeindex, vertexindex, bestplaneindex = -1;
8862         float d, bestd;
8863         vec3_t vert;
8864         const float *v;
8865         r_waterstate_waterplane_t *p;
8866         qboolean prepared = false;
8867         bestd = 0;
8868         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8869         {
8870                 if(p->camera_entity != rsurface.texture->camera_entity)
8871                         continue;
8872                 d = 0;
8873                 if(!prepared)
8874                 {
8875                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8876                         prepared = true;
8877                         if(rsurface.batchnumvertices == 0)
8878                                 break;
8879                 }
8880                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8881                 {
8882                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8883                         d += fabs(PlaneDiff(vert, &p->plane));
8884                 }
8885                 if (bestd > d || bestplaneindex < 0)
8886                 {
8887                         bestd = d;
8888                         bestplaneindex = planeindex;
8889                 }
8890         }
8891         return bestplaneindex;
8892         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8893         // this situation though, as it might be better to render single larger
8894         // batches with useless stuff (backface culled for example) than to
8895         // render multiple smaller batches
8896 }
8897
8898 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8899 {
8900         int i;
8901         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8902         rsurface.passcolor4f_vertexbuffer = 0;
8903         rsurface.passcolor4f_bufferoffset = 0;
8904         for (i = 0;i < rsurface.batchnumvertices;i++)
8905                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8906 }
8907
8908 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8909 {
8910         int i;
8911         float f;
8912         const float *v;
8913         const float *c;
8914         float *c2;
8915         if (rsurface.passcolor4f)
8916         {
8917                 // generate color arrays
8918                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8919                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8920                 rsurface.passcolor4f_vertexbuffer = 0;
8921                 rsurface.passcolor4f_bufferoffset = 0;
8922                 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)
8923                 {
8924                         f = RSurf_FogVertex(v);
8925                         c2[0] = c[0] * f;
8926                         c2[1] = c[1] * f;
8927                         c2[2] = c[2] * f;
8928                         c2[3] = c[3];
8929                 }
8930         }
8931         else
8932         {
8933                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8934                 rsurface.passcolor4f_vertexbuffer = 0;
8935                 rsurface.passcolor4f_bufferoffset = 0;
8936                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8937                 {
8938                         f = RSurf_FogVertex(v);
8939                         c2[0] = f;
8940                         c2[1] = f;
8941                         c2[2] = f;
8942                         c2[3] = 1;
8943                 }
8944         }
8945 }
8946
8947 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8948 {
8949         int i;
8950         float f;
8951         const float *v;
8952         const float *c;
8953         float *c2;
8954         if (!rsurface.passcolor4f)
8955                 return;
8956         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8957         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8958         rsurface.passcolor4f_vertexbuffer = 0;
8959         rsurface.passcolor4f_bufferoffset = 0;
8960         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)
8961         {
8962                 f = RSurf_FogVertex(v);
8963                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8964                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8965                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8966                 c2[3] = c[3];
8967         }
8968 }
8969
8970 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8971 {
8972         int i;
8973         const float *c;
8974         float *c2;
8975         if (!rsurface.passcolor4f)
8976                 return;
8977         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8978         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8979         rsurface.passcolor4f_vertexbuffer = 0;
8980         rsurface.passcolor4f_bufferoffset = 0;
8981         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8982         {
8983                 c2[0] = c[0] * r;
8984                 c2[1] = c[1] * g;
8985                 c2[2] = c[2] * b;
8986                 c2[3] = c[3] * a;
8987         }
8988 }
8989
8990 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
8991 {
8992         int i;
8993         const float *c;
8994         float *c2;
8995         if (!rsurface.passcolor4f)
8996                 return;
8997         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8998         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8999         rsurface.passcolor4f_vertexbuffer = 0;
9000         rsurface.passcolor4f_bufferoffset = 0;
9001         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9002         {
9003                 c2[0] = c[0] + r_refdef.scene.ambient;
9004                 c2[1] = c[1] + r_refdef.scene.ambient;
9005                 c2[2] = c[2] + r_refdef.scene.ambient;
9006                 c2[3] = c[3];
9007         }
9008 }
9009
9010 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9011 {
9012         // TODO: optimize
9013         rsurface.passcolor4f = NULL;
9014         rsurface.passcolor4f_vertexbuffer = 0;
9015         rsurface.passcolor4f_bufferoffset = 0;
9016         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9017         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9018         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9019         GL_Color(r, g, b, a);
9020         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9021         RSurf_DrawBatch();
9022 }
9023
9024 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9025 {
9026         // TODO: optimize applyfog && applycolor case
9027         // just apply fog if necessary, and tint the fog color array if necessary
9028         rsurface.passcolor4f = NULL;
9029         rsurface.passcolor4f_vertexbuffer = 0;
9030         rsurface.passcolor4f_bufferoffset = 0;
9031         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9032         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9033         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9034         GL_Color(r, g, b, a);
9035         RSurf_DrawBatch();
9036 }
9037
9038 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9039 {
9040         // TODO: optimize
9041         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9042         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9043         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9044         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9045         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9046         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9047         GL_Color(r, g, b, a);
9048         RSurf_DrawBatch();
9049 }
9050
9051 static void RSurf_DrawBatch_GL11_ClampColor(void)
9052 {
9053         int i;
9054         const float *c1;
9055         float *c2;
9056         if (!rsurface.passcolor4f)
9057                 return;
9058         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9059         {
9060                 c2[0] = bound(0.0f, c1[0], 1.0f);
9061                 c2[1] = bound(0.0f, c1[1], 1.0f);
9062                 c2[2] = bound(0.0f, c1[2], 1.0f);
9063                 c2[3] = bound(0.0f, c1[3], 1.0f);
9064         }
9065 }
9066
9067 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9068 {
9069         int i;
9070         float f;
9071         const float *v;
9072         const float *n;
9073         float *c;
9074         //vec3_t eyedir;
9075
9076         // fake shading
9077         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9078         rsurface.passcolor4f_vertexbuffer = 0;
9079         rsurface.passcolor4f_bufferoffset = 0;
9080         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)
9081         {
9082                 f = -DotProduct(r_refdef.view.forward, n);
9083                 f = max(0, f);
9084                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9085                 f *= r_refdef.lightmapintensity;
9086                 Vector4Set(c, f, f, f, 1);
9087         }
9088 }
9089
9090 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9091 {
9092         RSurf_DrawBatch_GL11_ApplyFakeLight();
9093         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9094         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9095         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9096         GL_Color(r, g, b, a);
9097         RSurf_DrawBatch();
9098 }
9099
9100 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9101 {
9102         int i;
9103         float f;
9104         float alpha;
9105         const float *v;
9106         const float *n;
9107         float *c;
9108         vec3_t ambientcolor;
9109         vec3_t diffusecolor;
9110         vec3_t lightdir;
9111         // TODO: optimize
9112         // model lighting
9113         VectorCopy(rsurface.modellight_lightdir, lightdir);
9114         f = 0.5f * r_refdef.lightmapintensity;
9115         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9116         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9117         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9118         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9119         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9120         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9121         alpha = *a;
9122         if (VectorLength2(diffusecolor) > 0)
9123         {
9124                 // q3-style directional shading
9125                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9126                 rsurface.passcolor4f_vertexbuffer = 0;
9127                 rsurface.passcolor4f_bufferoffset = 0;
9128                 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)
9129                 {
9130                         if ((f = DotProduct(n, lightdir)) > 0)
9131                                 VectorMA(ambientcolor, f, diffusecolor, c);
9132                         else
9133                                 VectorCopy(ambientcolor, c);
9134                         c[3] = alpha;
9135                 }
9136                 *r = 1;
9137                 *g = 1;
9138                 *b = 1;
9139                 *a = 1;
9140                 *applycolor = false;
9141         }
9142         else
9143         {
9144                 *r = ambientcolor[0];
9145                 *g = ambientcolor[1];
9146                 *b = ambientcolor[2];
9147                 rsurface.passcolor4f = NULL;
9148                 rsurface.passcolor4f_vertexbuffer = 0;
9149                 rsurface.passcolor4f_bufferoffset = 0;
9150         }
9151 }
9152
9153 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9154 {
9155         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9156         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9157         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9158         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9159         GL_Color(r, g, b, a);
9160         RSurf_DrawBatch();
9161 }
9162
9163 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9164 {
9165         int i;
9166         float f;
9167         const float *v;
9168         float *c;
9169         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9170         {
9171                 f = 1 - RSurf_FogVertex(v);
9172                 c[0] = r;
9173                 c[1] = g;
9174                 c[2] = b;
9175                 c[3] = f * a;
9176         }
9177 }
9178
9179 void RSurf_SetupDepthAndCulling(void)
9180 {
9181         // submodels are biased to avoid z-fighting with world surfaces that they
9182         // may be exactly overlapping (avoids z-fighting artifacts on certain
9183         // doors and things in Quake maps)
9184         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9185         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9186         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9187         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9188 }
9189
9190 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9191 {
9192         // transparent sky would be ridiculous
9193         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9194                 return;
9195         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9196         skyrenderlater = true;
9197         RSurf_SetupDepthAndCulling();
9198         GL_DepthMask(true);
9199         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9200         // skymasking on them, and Quake3 never did sky masking (unlike
9201         // software Quake and software Quake2), so disable the sky masking
9202         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9203         // and skymasking also looks very bad when noclipping outside the
9204         // level, so don't use it then either.
9205         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9206         {
9207                 R_Mesh_ResetTextureState();
9208                 if (skyrendermasked)
9209                 {
9210                         R_SetupShader_DepthOrShadow();
9211                         // depth-only (masking)
9212                         GL_ColorMask(0,0,0,0);
9213                         // just to make sure that braindead drivers don't draw
9214                         // anything despite that colormask...
9215                         GL_BlendFunc(GL_ZERO, GL_ONE);
9216                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9217                         if (rsurface.batchvertex3fbuffer)
9218                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9219                         else
9220                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9221                 }
9222                 else
9223                 {
9224                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9225                         // fog sky
9226                         GL_BlendFunc(GL_ONE, GL_ZERO);
9227                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9228                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9229                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9230                 }
9231                 RSurf_DrawBatch();
9232                 if (skyrendermasked)
9233                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9234         }
9235         R_Mesh_ResetTextureState();
9236         GL_Color(1, 1, 1, 1);
9237 }
9238
9239 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9240 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9241 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9242 {
9243         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9244                 return;
9245         if (prepass)
9246         {
9247                 // render screenspace normalmap to texture
9248                 GL_DepthMask(true);
9249                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9250                 RSurf_DrawBatch();
9251                 return;
9252         }
9253
9254         // bind lightmap texture
9255
9256         // water/refraction/reflection/camera surfaces have to be handled specially
9257         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9258         {
9259                 int start, end, startplaneindex;
9260                 for (start = 0;start < texturenumsurfaces;start = end)
9261                 {
9262                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9263                         if(startplaneindex < 0)
9264                         {
9265                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9266                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9267                                 end = start + 1;
9268                                 continue;
9269                         }
9270                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9271                                 ;
9272                         // now that we have a batch using the same planeindex, render it
9273                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9274                         {
9275                                 // render water or distortion background
9276                                 GL_DepthMask(true);
9277                                 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));
9278                                 RSurf_DrawBatch();
9279                                 // blend surface on top
9280                                 GL_DepthMask(false);
9281                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9282                                 RSurf_DrawBatch();
9283                         }
9284                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9285                         {
9286                                 // render surface with reflection texture as input
9287                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9288                                 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));
9289                                 RSurf_DrawBatch();
9290                         }
9291                 }
9292                 return;
9293         }
9294
9295         // render surface batch normally
9296         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9297         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9298         RSurf_DrawBatch();
9299 }
9300
9301 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9302 {
9303         // OpenGL 1.3 path - anything not completely ancient
9304         qboolean applycolor;
9305         qboolean applyfog;
9306         int layerindex;
9307         const texturelayer_t *layer;
9308         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);
9309         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9310
9311         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9312         {
9313                 vec4_t layercolor;
9314                 int layertexrgbscale;
9315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9316                 {
9317                         if (layerindex == 0)
9318                                 GL_AlphaTest(true);
9319                         else
9320                         {
9321                                 GL_AlphaTest(false);
9322                                 GL_DepthFunc(GL_EQUAL);
9323                         }
9324                 }
9325                 GL_DepthMask(layer->depthmask && writedepth);
9326                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9327                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9328                 {
9329                         layertexrgbscale = 4;
9330                         VectorScale(layer->color, 0.25f, layercolor);
9331                 }
9332                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9333                 {
9334                         layertexrgbscale = 2;
9335                         VectorScale(layer->color, 0.5f, layercolor);
9336                 }
9337                 else
9338                 {
9339                         layertexrgbscale = 1;
9340                         VectorScale(layer->color, 1.0f, layercolor);
9341                 }
9342                 layercolor[3] = layer->color[3];
9343                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9344                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9345                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9346                 switch (layer->type)
9347                 {
9348                 case TEXTURELAYERTYPE_LITTEXTURE:
9349                         // single-pass lightmapped texture with 2x rgbscale
9350                         R_Mesh_TexBind(0, r_texture_white);
9351                         R_Mesh_TexMatrix(0, NULL);
9352                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9353                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9354                         R_Mesh_TexBind(1, layer->texture);
9355                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9356                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9357                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9358                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9359                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9360                         else if (FAKELIGHT_ENABLED)
9361                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9362                         else if (rsurface.uselightmaptexture)
9363                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9364                         else
9365                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9366                         break;
9367                 case TEXTURELAYERTYPE_TEXTURE:
9368                         // singletexture unlit texture with transparency support
9369                         R_Mesh_TexBind(0, layer->texture);
9370                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9371                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9372                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9373                         R_Mesh_TexBind(1, 0);
9374                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9375                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9376                         break;
9377                 case TEXTURELAYERTYPE_FOG:
9378                         // singletexture fogging
9379                         if (layer->texture)
9380                         {
9381                                 R_Mesh_TexBind(0, layer->texture);
9382                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9383                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9384                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9385                         }
9386                         else
9387                         {
9388                                 R_Mesh_TexBind(0, 0);
9389                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9390                         }
9391                         R_Mesh_TexBind(1, 0);
9392                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9393                         // generate a color array for the fog pass
9394                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9395                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9396                         RSurf_DrawBatch();
9397                         break;
9398                 default:
9399                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9400                 }
9401         }
9402         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9403         {
9404                 GL_DepthFunc(GL_LEQUAL);
9405                 GL_AlphaTest(false);
9406         }
9407 }
9408
9409 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9410 {
9411         // OpenGL 1.1 - crusty old voodoo path
9412         qboolean applyfog;
9413         int layerindex;
9414         const texturelayer_t *layer;
9415         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);
9416         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9417
9418         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9419         {
9420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9421                 {
9422                         if (layerindex == 0)
9423                                 GL_AlphaTest(true);
9424                         else
9425                         {
9426                                 GL_AlphaTest(false);
9427                                 GL_DepthFunc(GL_EQUAL);
9428                         }
9429                 }
9430                 GL_DepthMask(layer->depthmask && writedepth);
9431                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9432                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9433                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9434                 switch (layer->type)
9435                 {
9436                 case TEXTURELAYERTYPE_LITTEXTURE:
9437                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9438                         {
9439                                 // two-pass lit texture with 2x rgbscale
9440                                 // first the lightmap pass
9441                                 R_Mesh_TexBind(0, r_texture_white);
9442                                 R_Mesh_TexMatrix(0, NULL);
9443                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9444                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9445                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9446                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9447                                 else if (FAKELIGHT_ENABLED)
9448                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9449                                 else if (rsurface.uselightmaptexture)
9450                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9451                                 else
9452                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9453                                 // then apply the texture to it
9454                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9455                                 R_Mesh_TexBind(0, layer->texture);
9456                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9457                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9458                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9459                                 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);
9460                         }
9461                         else
9462                         {
9463                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9464                                 R_Mesh_TexBind(0, layer->texture);
9465                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9466                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9467                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9468                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9469                                         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);
9470                                 else
9471                                         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);
9472                         }
9473                         break;
9474                 case TEXTURELAYERTYPE_TEXTURE:
9475                         // singletexture unlit texture with transparency support
9476                         R_Mesh_TexBind(0, layer->texture);
9477                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9478                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9479                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9480                         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);
9481                         break;
9482                 case TEXTURELAYERTYPE_FOG:
9483                         // singletexture fogging
9484                         if (layer->texture)
9485                         {
9486                                 R_Mesh_TexBind(0, layer->texture);
9487                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9488                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9489                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9490                         }
9491                         else
9492                         {
9493                                 R_Mesh_TexBind(0, 0);
9494                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9495                         }
9496                         // generate a color array for the fog pass
9497                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9498                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9499                         RSurf_DrawBatch();
9500                         break;
9501                 default:
9502                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9503                 }
9504         }
9505         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9506         {
9507                 GL_DepthFunc(GL_LEQUAL);
9508                 GL_AlphaTest(false);
9509         }
9510 }
9511
9512 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9513 {
9514         int vi;
9515         int j;
9516         r_vertexgeneric_t *batchvertex;
9517         float c[4];
9518
9519 //      R_Mesh_ResetTextureState();
9520         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9521
9522         if(rsurface.texture && rsurface.texture->currentskinframe)
9523         {
9524                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9525                 c[3] *= rsurface.texture->currentalpha;
9526         }
9527         else
9528         {
9529                 c[0] = 1;
9530                 c[1] = 0;
9531                 c[2] = 1;
9532                 c[3] = 1;
9533         }
9534
9535         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9536         {
9537                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9538                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9539                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9540         }
9541
9542         // brighten it up (as texture value 127 means "unlit")
9543         c[0] *= 2 * r_refdef.view.colorscale;
9544         c[1] *= 2 * r_refdef.view.colorscale;
9545         c[2] *= 2 * r_refdef.view.colorscale;
9546
9547         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9548                 c[3] *= r_wateralpha.value;
9549
9550         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9551         {
9552                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9553                 GL_DepthMask(false);
9554         }
9555         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9556         {
9557                 GL_BlendFunc(GL_ONE, GL_ONE);
9558                 GL_DepthMask(false);
9559         }
9560         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9561         {
9562                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9563                 GL_DepthMask(false);
9564         }
9565         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9566         {
9567                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9568                 GL_DepthMask(false);
9569         }
9570         else
9571         {
9572                 GL_BlendFunc(GL_ONE, GL_ZERO);
9573                 GL_DepthMask(writedepth);
9574         }
9575
9576         if (r_showsurfaces.integer == 3)
9577         {
9578                 rsurface.passcolor4f = NULL;
9579
9580                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9581                 {
9582                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9583
9584                         rsurface.passcolor4f = NULL;
9585                         rsurface.passcolor4f_vertexbuffer = 0;
9586                         rsurface.passcolor4f_bufferoffset = 0;
9587                 }
9588                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9589                 {
9590                         qboolean applycolor = true;
9591                         float one = 1.0;
9592
9593                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9594
9595                         r_refdef.lightmapintensity = 1;
9596                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9597                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9598                 }
9599                 else if (FAKELIGHT_ENABLED)
9600                 {
9601                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9602
9603                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9604                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9605                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9606                 }
9607                 else
9608                 {
9609                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9610
9611                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9612                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9613                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9614                 }
9615
9616                 if(!rsurface.passcolor4f)
9617                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9618
9619                 RSurf_DrawBatch_GL11_ApplyAmbient();
9620                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9621                 if(r_refdef.fogenabled)
9622                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9623                 RSurf_DrawBatch_GL11_ClampColor();
9624
9625                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9626                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9627                 RSurf_DrawBatch();
9628         }
9629         else if (!r_refdef.view.showdebug)
9630         {
9631                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9632                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9633                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9634                 {
9635                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9636                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9637                 }
9638                 R_Mesh_PrepareVertices_Generic_Unlock();
9639                 RSurf_DrawBatch();
9640         }
9641         else if (r_showsurfaces.integer == 4)
9642         {
9643                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9644                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9645                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9646                 {
9647                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9648                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9649                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9650                 }
9651                 R_Mesh_PrepareVertices_Generic_Unlock();
9652                 RSurf_DrawBatch();
9653         }
9654         else if (r_showsurfaces.integer == 2)
9655         {
9656                 const int *e;
9657                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9658                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9659                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9660                 {
9661                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9662                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9663                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9664                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9665                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9666                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9667                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9668                 }
9669                 R_Mesh_PrepareVertices_Generic_Unlock();
9670                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9671         }
9672         else
9673         {
9674                 int texturesurfaceindex;
9675                 int k;
9676                 const msurface_t *surface;
9677                 float surfacecolor4f[4];
9678                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9679                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9680                 vi = 0;
9681                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9682                 {
9683                         surface = texturesurfacelist[texturesurfaceindex];
9684                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9685                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9686                         for (j = 0;j < surface->num_vertices;j++)
9687                         {
9688                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9689                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9690                                 vi++;
9691                         }
9692                 }
9693                 R_Mesh_PrepareVertices_Generic_Unlock();
9694                 RSurf_DrawBatch();
9695         }
9696 }
9697
9698 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9699 {
9700         CHECKGLERROR
9701         RSurf_SetupDepthAndCulling();
9702         if (r_showsurfaces.integer)
9703         {
9704                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9705                 return;
9706         }
9707         switch (vid.renderpath)
9708         {
9709         case RENDERPATH_GL20:
9710         case RENDERPATH_D3D9:
9711         case RENDERPATH_D3D10:
9712         case RENDERPATH_D3D11:
9713         case RENDERPATH_SOFT:
9714         case RENDERPATH_GLES2:
9715                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9716                 break;
9717         case RENDERPATH_GL13:
9718                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9719                 break;
9720         case RENDERPATH_GL11:
9721                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9722                 break;
9723         }
9724         CHECKGLERROR
9725 }
9726
9727 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9728 {
9729         CHECKGLERROR
9730         RSurf_SetupDepthAndCulling();
9731         if (r_showsurfaces.integer)
9732         {
9733                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9734                 return;
9735         }
9736         switch (vid.renderpath)
9737         {
9738         case RENDERPATH_GL20:
9739         case RENDERPATH_D3D9:
9740         case RENDERPATH_D3D10:
9741         case RENDERPATH_D3D11:
9742         case RENDERPATH_SOFT:
9743         case RENDERPATH_GLES2:
9744                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9745                 break;
9746         case RENDERPATH_GL13:
9747                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9748                 break;
9749         case RENDERPATH_GL11:
9750                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9751                 break;
9752         }
9753         CHECKGLERROR
9754 }
9755
9756 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9757 {
9758         int i, j;
9759         int texturenumsurfaces, endsurface;
9760         texture_t *texture;
9761         const msurface_t *surface;
9762 #define MAXBATCH_TRANSPARENTSURFACES 256
9763         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9764
9765         // if the model is static it doesn't matter what value we give for
9766         // wantnormals and wanttangents, so this logic uses only rules applicable
9767         // to a model, knowing that they are meaningless otherwise
9768         if (ent == r_refdef.scene.worldentity)
9769                 RSurf_ActiveWorldEntity();
9770         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9771                 RSurf_ActiveModelEntity(ent, false, false, false);
9772         else
9773         {
9774                 switch (vid.renderpath)
9775                 {
9776                 case RENDERPATH_GL20:
9777                 case RENDERPATH_D3D9:
9778                 case RENDERPATH_D3D10:
9779                 case RENDERPATH_D3D11:
9780                 case RENDERPATH_SOFT:
9781                 case RENDERPATH_GLES2:
9782                         RSurf_ActiveModelEntity(ent, true, true, false);
9783                         break;
9784                 case RENDERPATH_GL13:
9785                 case RENDERPATH_GL11:
9786                         RSurf_ActiveModelEntity(ent, true, false, false);
9787                         break;
9788                 }
9789         }
9790
9791         if (r_transparentdepthmasking.integer)
9792         {
9793                 qboolean setup = false;
9794                 for (i = 0;i < numsurfaces;i = j)
9795                 {
9796                         j = i + 1;
9797                         surface = rsurface.modelsurfaces + surfacelist[i];
9798                         texture = surface->texture;
9799                         rsurface.texture = R_GetCurrentTexture(texture);
9800                         rsurface.lightmaptexture = NULL;
9801                         rsurface.deluxemaptexture = NULL;
9802                         rsurface.uselightmaptexture = false;
9803                         // scan ahead until we find a different texture
9804                         endsurface = min(i + 1024, numsurfaces);
9805                         texturenumsurfaces = 0;
9806                         texturesurfacelist[texturenumsurfaces++] = surface;
9807                         for (;j < endsurface;j++)
9808                         {
9809                                 surface = rsurface.modelsurfaces + surfacelist[j];
9810                                 if (texture != surface->texture)
9811                                         break;
9812                                 texturesurfacelist[texturenumsurfaces++] = surface;
9813                         }
9814                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9815                                 continue;
9816                         // render the range of surfaces as depth
9817                         if (!setup)
9818                         {
9819                                 setup = true;
9820                                 GL_ColorMask(0,0,0,0);
9821                                 GL_Color(1,1,1,1);
9822                                 GL_DepthTest(true);
9823                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9824                                 GL_DepthMask(true);
9825 //                              R_Mesh_ResetTextureState();
9826                                 R_SetupShader_DepthOrShadow();
9827                         }
9828                         RSurf_SetupDepthAndCulling();
9829                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9830                         if (rsurface.batchvertex3fbuffer)
9831                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9832                         else
9833                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9834                         RSurf_DrawBatch();
9835                 }
9836                 if (setup)
9837                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9838         }
9839
9840         for (i = 0;i < numsurfaces;i = j)
9841         {
9842                 j = i + 1;
9843                 surface = rsurface.modelsurfaces + surfacelist[i];
9844                 texture = surface->texture;
9845                 rsurface.texture = R_GetCurrentTexture(texture);
9846                 // scan ahead until we find a different texture
9847                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9848                 texturenumsurfaces = 0;
9849                 texturesurfacelist[texturenumsurfaces++] = surface;
9850                 if(FAKELIGHT_ENABLED)
9851                 {
9852                         rsurface.lightmaptexture = NULL;
9853                         rsurface.deluxemaptexture = NULL;
9854                         rsurface.uselightmaptexture = false;
9855                         for (;j < endsurface;j++)
9856                         {
9857                                 surface = rsurface.modelsurfaces + surfacelist[j];
9858                                 if (texture != surface->texture)
9859                                         break;
9860                                 texturesurfacelist[texturenumsurfaces++] = surface;
9861                         }
9862                 }
9863                 else
9864                 {
9865                         rsurface.lightmaptexture = surface->lightmaptexture;
9866                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9867                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9868                         for (;j < endsurface;j++)
9869                         {
9870                                 surface = rsurface.modelsurfaces + surfacelist[j];
9871                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9872                                         break;
9873                                 texturesurfacelist[texturenumsurfaces++] = surface;
9874                         }
9875                 }
9876                 // render the range of surfaces
9877                 if (ent == r_refdef.scene.worldentity)
9878                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9879                 else
9880                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9881         }
9882         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9883 }
9884
9885 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9886 {
9887         // transparent surfaces get pushed off into the transparent queue
9888         int surfacelistindex;
9889         const msurface_t *surface;
9890         vec3_t tempcenter, center;
9891         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9892         {
9893                 surface = texturesurfacelist[surfacelistindex];
9894                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9895                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9896                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9897                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9898                 if (queueentity->transparent_offset) // transparent offset
9899                 {
9900                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9901                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9902                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9903                 }
9904                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9905         }
9906 }
9907
9908 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9909 {
9910         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9911                 return;
9912         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9913                 return;
9914         RSurf_SetupDepthAndCulling();
9915         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9916         if (rsurface.batchvertex3fbuffer)
9917                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9918         else
9919                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9920         RSurf_DrawBatch();
9921 }
9922
9923 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9924 {
9925         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9926         CHECKGLERROR
9927         if (depthonly)
9928                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9929         else if (prepass)
9930         {
9931                 if (!rsurface.texture->currentnumlayers)
9932                         return;
9933                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9934                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9935                 else
9936                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9937         }
9938         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9939                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9940         else if (!rsurface.texture->currentnumlayers)
9941                 return;
9942         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9943         {
9944                 // in the deferred case, transparent surfaces were queued during prepass
9945                 if (!r_shadow_usingdeferredprepass)
9946                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9947         }
9948         else
9949         {
9950                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9951                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9952         }
9953         CHECKGLERROR
9954 }
9955
9956 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9957 {
9958         int i, j;
9959         texture_t *texture;
9960         R_FrameData_SetMark();
9961         // break the surface list down into batches by texture and use of lightmapping
9962         for (i = 0;i < numsurfaces;i = j)
9963         {
9964                 j = i + 1;
9965                 // texture is the base texture pointer, rsurface.texture is the
9966                 // current frame/skin the texture is directing us to use (for example
9967                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9968                 // use skin 1 instead)
9969                 texture = surfacelist[i]->texture;
9970                 rsurface.texture = R_GetCurrentTexture(texture);
9971                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9972                 {
9973                         // if this texture is not the kind we want, skip ahead to the next one
9974                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9975                                 ;
9976                         continue;
9977                 }
9978                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9979                 {
9980                         rsurface.lightmaptexture = NULL;
9981                         rsurface.deluxemaptexture = NULL;
9982                         rsurface.uselightmaptexture = false;
9983                         // simply scan ahead until we find a different texture or lightmap state
9984                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9985                                 ;
9986                 }
9987                 else
9988                 {
9989                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9990                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9991                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
9992                         // simply scan ahead until we find a different texture or lightmap state
9993                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
9994                                 ;
9995                 }
9996                 // render the range of surfaces
9997                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
9998         }
9999         R_FrameData_ReturnToMark();
10000 }
10001
10002 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10003 {
10004         CHECKGLERROR
10005         if (depthonly)
10006                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10007         else if (prepass)
10008         {
10009                 if (!rsurface.texture->currentnumlayers)
10010                         return;
10011                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10012                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10013                 else
10014                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10015         }
10016         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10017                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10018         else if (!rsurface.texture->currentnumlayers)
10019                 return;
10020         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10021         {
10022                 // in the deferred case, transparent surfaces were queued during prepass
10023                 if (!r_shadow_usingdeferredprepass)
10024                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10025         }
10026         else
10027         {
10028                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10029                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10030         }
10031         CHECKGLERROR
10032 }
10033
10034 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10035 {
10036         int i, j;
10037         texture_t *texture;
10038         R_FrameData_SetMark();
10039         // break the surface list down into batches by texture and use of lightmapping
10040         for (i = 0;i < numsurfaces;i = j)
10041         {
10042                 j = i + 1;
10043                 // texture is the base texture pointer, rsurface.texture is the
10044                 // current frame/skin the texture is directing us to use (for example
10045                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10046                 // use skin 1 instead)
10047                 texture = surfacelist[i]->texture;
10048                 rsurface.texture = R_GetCurrentTexture(texture);
10049                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10050                 {
10051                         // if this texture is not the kind we want, skip ahead to the next one
10052                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10053                                 ;
10054                         continue;
10055                 }
10056                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10057                 {
10058                         rsurface.lightmaptexture = NULL;
10059                         rsurface.deluxemaptexture = NULL;
10060                         rsurface.uselightmaptexture = false;
10061                         // simply scan ahead until we find a different texture or lightmap state
10062                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10063                                 ;
10064                 }
10065                 else
10066                 {
10067                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10068                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10069                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10070                         // simply scan ahead until we find a different texture or lightmap state
10071                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10072                                 ;
10073                 }
10074                 // render the range of surfaces
10075                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10076         }
10077         R_FrameData_ReturnToMark();
10078 }
10079
10080 float locboxvertex3f[6*4*3] =
10081 {
10082         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10083         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10084         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10085         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10086         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10087         1,0,0, 0,0,0, 0,1,0, 1,1,0
10088 };
10089
10090 unsigned short locboxelements[6*2*3] =
10091 {
10092          0, 1, 2, 0, 2, 3,
10093          4, 5, 6, 4, 6, 7,
10094          8, 9,10, 8,10,11,
10095         12,13,14, 12,14,15,
10096         16,17,18, 16,18,19,
10097         20,21,22, 20,22,23
10098 };
10099
10100 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10101 {
10102         int i, j;
10103         cl_locnode_t *loc = (cl_locnode_t *)ent;
10104         vec3_t mins, size;
10105         float vertex3f[6*4*3];
10106         CHECKGLERROR
10107         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10108         GL_DepthMask(false);
10109         GL_DepthRange(0, 1);
10110         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10111         GL_DepthTest(true);
10112         GL_CullFace(GL_NONE);
10113         R_EntityMatrix(&identitymatrix);
10114
10115 //      R_Mesh_ResetTextureState();
10116
10117         i = surfacelist[0];
10118         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10119                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10120                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10121                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10122
10123         if (VectorCompare(loc->mins, loc->maxs))
10124         {
10125                 VectorSet(size, 2, 2, 2);
10126                 VectorMA(loc->mins, -0.5f, size, mins);
10127         }
10128         else
10129         {
10130                 VectorCopy(loc->mins, mins);
10131                 VectorSubtract(loc->maxs, loc->mins, size);
10132         }
10133
10134         for (i = 0;i < 6*4*3;)
10135                 for (j = 0;j < 3;j++, i++)
10136                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10137
10138         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10139         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10140         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10141 }
10142
10143 void R_DrawLocs(void)
10144 {
10145         int index;
10146         cl_locnode_t *loc, *nearestloc;
10147         vec3_t center;
10148         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10149         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10150         {
10151                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10152                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10153         }
10154 }
10155
10156 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10157 {
10158         if (decalsystem->decals)
10159                 Mem_Free(decalsystem->decals);
10160         memset(decalsystem, 0, sizeof(*decalsystem));
10161 }
10162
10163 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)
10164 {
10165         tridecal_t *decal;
10166         tridecal_t *decals;
10167         int i;
10168
10169         // expand or initialize the system
10170         if (decalsystem->maxdecals <= decalsystem->numdecals)
10171         {
10172                 decalsystem_t old = *decalsystem;
10173                 qboolean useshortelements;
10174                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10175                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10176                 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)));
10177                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10178                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10179                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10180                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10181                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10182                 if (decalsystem->numdecals)
10183                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10184                 if (old.decals)
10185                         Mem_Free(old.decals);
10186                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10187                         decalsystem->element3i[i] = i;
10188                 if (useshortelements)
10189                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10190                                 decalsystem->element3s[i] = i;
10191         }
10192
10193         // grab a decal and search for another free slot for the next one
10194         decals = decalsystem->decals;
10195         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10196         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10197                 ;
10198         decalsystem->freedecal = i;
10199         if (decalsystem->numdecals <= i)
10200                 decalsystem->numdecals = i + 1;
10201
10202         // initialize the decal
10203         decal->lived = 0;
10204         decal->triangleindex = triangleindex;
10205         decal->surfaceindex = surfaceindex;
10206         decal->decalsequence = decalsequence;
10207         decal->color4f[0][0] = c0[0];
10208         decal->color4f[0][1] = c0[1];
10209         decal->color4f[0][2] = c0[2];
10210         decal->color4f[0][3] = 1;
10211         decal->color4f[1][0] = c1[0];
10212         decal->color4f[1][1] = c1[1];
10213         decal->color4f[1][2] = c1[2];
10214         decal->color4f[1][3] = 1;
10215         decal->color4f[2][0] = c2[0];
10216         decal->color4f[2][1] = c2[1];
10217         decal->color4f[2][2] = c2[2];
10218         decal->color4f[2][3] = 1;
10219         decal->vertex3f[0][0] = v0[0];
10220         decal->vertex3f[0][1] = v0[1];
10221         decal->vertex3f[0][2] = v0[2];
10222         decal->vertex3f[1][0] = v1[0];
10223         decal->vertex3f[1][1] = v1[1];
10224         decal->vertex3f[1][2] = v1[2];
10225         decal->vertex3f[2][0] = v2[0];
10226         decal->vertex3f[2][1] = v2[1];
10227         decal->vertex3f[2][2] = v2[2];
10228         decal->texcoord2f[0][0] = t0[0];
10229         decal->texcoord2f[0][1] = t0[1];
10230         decal->texcoord2f[1][0] = t1[0];
10231         decal->texcoord2f[1][1] = t1[1];
10232         decal->texcoord2f[2][0] = t2[0];
10233         decal->texcoord2f[2][1] = t2[1];
10234 }
10235
10236 extern cvar_t cl_decals_bias;
10237 extern cvar_t cl_decals_models;
10238 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10239 // baseparms, parms, temps
10240 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)
10241 {
10242         int cornerindex;
10243         int index;
10244         float v[9][3];
10245         const float *vertex3f;
10246         const float *normal3f;
10247         int numpoints;
10248         float points[2][9][3];
10249         float temp[3];
10250         float tc[9][2];
10251         float f;
10252         float c[9][4];
10253         const int *e;
10254
10255         e = rsurface.modelelement3i + 3*triangleindex;
10256
10257         vertex3f = rsurface.modelvertex3f;
10258         normal3f = rsurface.modelnormal3f;
10259
10260         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10261         {
10262                 index = 3*e[cornerindex];
10263                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10264         }
10265         // cull backfaces
10266         //TriangleNormal(v[0], v[1], v[2], normal);
10267         //if (DotProduct(normal, localnormal) < 0.0f)
10268         //      continue;
10269         // clip by each of the box planes formed from the projection matrix
10270         // if anything survives, we emit the decal
10271         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]);
10272         if (numpoints < 3)
10273                 return;
10274         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]);
10275         if (numpoints < 3)
10276                 return;
10277         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]);
10278         if (numpoints < 3)
10279                 return;
10280         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]);
10281         if (numpoints < 3)
10282                 return;
10283         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]);
10284         if (numpoints < 3)
10285                 return;
10286         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]);
10287         if (numpoints < 3)
10288                 return;
10289         // some part of the triangle survived, so we have to accept it...
10290         if (dynamic)
10291         {
10292                 // dynamic always uses the original triangle
10293                 numpoints = 3;
10294                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10295                 {
10296                         index = 3*e[cornerindex];
10297                         VectorCopy(vertex3f + index, v[cornerindex]);
10298                 }
10299         }
10300         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10301         {
10302                 // convert vertex positions to texcoords
10303                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10304                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10305                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10306                 // calculate distance fade from the projection origin
10307                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10308                 f = bound(0.0f, f, 1.0f);
10309                 c[cornerindex][0] = r * f;
10310                 c[cornerindex][1] = g * f;
10311                 c[cornerindex][2] = b * f;
10312                 c[cornerindex][3] = 1.0f;
10313                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10314         }
10315         if (dynamic)
10316                 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);
10317         else
10318                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10319                         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);
10320 }
10321 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)
10322 {
10323         matrix4x4_t projection;
10324         decalsystem_t *decalsystem;
10325         qboolean dynamic;
10326         dp_model_t *model;
10327         const msurface_t *surface;
10328         const msurface_t *surfaces;
10329         const int *surfacelist;
10330         const texture_t *texture;
10331         int numtriangles;
10332         int numsurfacelist;
10333         int surfacelistindex;
10334         int surfaceindex;
10335         int triangleindex;
10336         float localorigin[3];
10337         float localnormal[3];
10338         float localmins[3];
10339         float localmaxs[3];
10340         float localsize;
10341         //float normal[3];
10342         float planes[6][4];
10343         float angles[3];
10344         bih_t *bih;
10345         int bih_triangles_count;
10346         int bih_triangles[256];
10347         int bih_surfaces[256];
10348
10349         decalsystem = &ent->decalsystem;
10350         model = ent->model;
10351         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10352         {
10353                 R_DecalSystem_Reset(&ent->decalsystem);
10354                 return;
10355         }
10356
10357         if (!model->brush.data_leafs && !cl_decals_models.integer)
10358         {
10359                 if (decalsystem->model)
10360                         R_DecalSystem_Reset(decalsystem);
10361                 return;
10362         }
10363
10364         if (decalsystem->model != model)
10365                 R_DecalSystem_Reset(decalsystem);
10366         decalsystem->model = model;
10367
10368         RSurf_ActiveModelEntity(ent, true, false, false);
10369
10370         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10371         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10372         VectorNormalize(localnormal);
10373         localsize = worldsize*rsurface.inversematrixscale;
10374         localmins[0] = localorigin[0] - localsize;
10375         localmins[1] = localorigin[1] - localsize;
10376         localmins[2] = localorigin[2] - localsize;
10377         localmaxs[0] = localorigin[0] + localsize;
10378         localmaxs[1] = localorigin[1] + localsize;
10379         localmaxs[2] = localorigin[2] + localsize;
10380
10381         //VectorCopy(localnormal, planes[4]);
10382         //VectorVectors(planes[4], planes[2], planes[0]);
10383         AnglesFromVectors(angles, localnormal, NULL, false);
10384         AngleVectors(angles, planes[0], planes[2], planes[4]);
10385         VectorNegate(planes[0], planes[1]);
10386         VectorNegate(planes[2], planes[3]);
10387         VectorNegate(planes[4], planes[5]);
10388         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10389         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10390         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10391         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10392         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10393         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10394
10395 #if 1
10396 // works
10397 {
10398         matrix4x4_t forwardprojection;
10399         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10400         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10401 }
10402 #else
10403 // broken
10404 {
10405         float projectionvector[4][3];
10406         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10407         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10408         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10409         projectionvector[0][0] = planes[0][0] * ilocalsize;
10410         projectionvector[0][1] = planes[1][0] * ilocalsize;
10411         projectionvector[0][2] = planes[2][0] * ilocalsize;
10412         projectionvector[1][0] = planes[0][1] * ilocalsize;
10413         projectionvector[1][1] = planes[1][1] * ilocalsize;
10414         projectionvector[1][2] = planes[2][1] * ilocalsize;
10415         projectionvector[2][0] = planes[0][2] * ilocalsize;
10416         projectionvector[2][1] = planes[1][2] * ilocalsize;
10417         projectionvector[2][2] = planes[2][2] * ilocalsize;
10418         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10419         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10420         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10421         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10422 }
10423 #endif
10424
10425         dynamic = model->surfmesh.isanimated;
10426         numsurfacelist = model->nummodelsurfaces;
10427         surfacelist = model->sortedmodelsurfaces;
10428         surfaces = model->data_surfaces;
10429
10430         bih = NULL;
10431         bih_triangles_count = -1;
10432         if(!dynamic)
10433         {
10434                 if(model->render_bih.numleafs)
10435                         bih = &model->render_bih;
10436                 else if(model->collision_bih.numleafs)
10437                         bih = &model->collision_bih;
10438         }
10439         if(bih)
10440                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10441         if(bih_triangles_count == 0)
10442                 return;
10443         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10444                 return;
10445         if(bih_triangles_count > 0)
10446         {
10447                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10448                 {
10449                         surfaceindex = bih_surfaces[triangleindex];
10450                         surface = surfaces + surfaceindex;
10451                         texture = surface->texture;
10452                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10453                                 continue;
10454                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10455                                 continue;
10456                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10457                 }
10458         }
10459         else
10460         {
10461                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10462                 {
10463                         surfaceindex = surfacelist[surfacelistindex];
10464                         surface = surfaces + surfaceindex;
10465                         // check cull box first because it rejects more than any other check
10466                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10467                                 continue;
10468                         // skip transparent surfaces
10469                         texture = surface->texture;
10470                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10471                                 continue;
10472                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10473                                 continue;
10474                         numtriangles = surface->num_triangles;
10475                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10476                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10477                 }
10478         }
10479 }
10480
10481 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10482 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)
10483 {
10484         int renderentityindex;
10485         float worldmins[3];
10486         float worldmaxs[3];
10487         entity_render_t *ent;
10488
10489         if (!cl_decals_newsystem.integer)
10490                 return;
10491
10492         worldmins[0] = worldorigin[0] - worldsize;
10493         worldmins[1] = worldorigin[1] - worldsize;
10494         worldmins[2] = worldorigin[2] - worldsize;
10495         worldmaxs[0] = worldorigin[0] + worldsize;
10496         worldmaxs[1] = worldorigin[1] + worldsize;
10497         worldmaxs[2] = worldorigin[2] + worldsize;
10498
10499         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10500
10501         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10502         {
10503                 ent = r_refdef.scene.entities[renderentityindex];
10504                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10505                         continue;
10506
10507                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10508         }
10509 }
10510
10511 typedef struct r_decalsystem_splatqueue_s
10512 {
10513         vec3_t worldorigin;
10514         vec3_t worldnormal;
10515         float color[4];
10516         float tcrange[4];
10517         float worldsize;
10518         int decalsequence;
10519 }
10520 r_decalsystem_splatqueue_t;
10521
10522 int r_decalsystem_numqueued = 0;
10523 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10524
10525 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)
10526 {
10527         r_decalsystem_splatqueue_t *queue;
10528
10529         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10530                 return;
10531
10532         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10533         VectorCopy(worldorigin, queue->worldorigin);
10534         VectorCopy(worldnormal, queue->worldnormal);
10535         Vector4Set(queue->color, r, g, b, a);
10536         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10537         queue->worldsize = worldsize;
10538         queue->decalsequence = cl.decalsequence++;
10539 }
10540
10541 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10542 {
10543         int i;
10544         r_decalsystem_splatqueue_t *queue;
10545
10546         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10547                 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);
10548         r_decalsystem_numqueued = 0;
10549 }
10550
10551 extern cvar_t cl_decals_max;
10552 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10553 {
10554         int i;
10555         decalsystem_t *decalsystem = &ent->decalsystem;
10556         int numdecals;
10557         int killsequence;
10558         tridecal_t *decal;
10559         float frametime;
10560         float lifetime;
10561
10562         if (!decalsystem->numdecals)
10563                 return;
10564
10565         if (r_showsurfaces.integer)
10566                 return;
10567
10568         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10569         {
10570                 R_DecalSystem_Reset(decalsystem);
10571                 return;
10572         }
10573
10574         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10575         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10576
10577         if (decalsystem->lastupdatetime)
10578                 frametime = (cl.time - decalsystem->lastupdatetime);
10579         else
10580                 frametime = 0;
10581         decalsystem->lastupdatetime = cl.time;
10582         decal = decalsystem->decals;
10583         numdecals = decalsystem->numdecals;
10584
10585         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10586         {
10587                 if (decal->color4f[0][3])
10588                 {
10589                         decal->lived += frametime;
10590                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10591                         {
10592                                 memset(decal, 0, sizeof(*decal));
10593                                 if (decalsystem->freedecal > i)
10594                                         decalsystem->freedecal = i;
10595                         }
10596                 }
10597         }
10598         decal = decalsystem->decals;
10599         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10600                 numdecals--;
10601
10602         // collapse the array by shuffling the tail decals into the gaps
10603         for (;;)
10604         {
10605                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10606                         decalsystem->freedecal++;
10607                 if (decalsystem->freedecal == numdecals)
10608                         break;
10609                 decal[decalsystem->freedecal] = decal[--numdecals];
10610         }
10611
10612         decalsystem->numdecals = numdecals;
10613
10614         if (numdecals <= 0)
10615         {
10616                 // if there are no decals left, reset decalsystem
10617                 R_DecalSystem_Reset(decalsystem);
10618         }
10619 }
10620
10621 extern skinframe_t *decalskinframe;
10622 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10623 {
10624         int i;
10625         decalsystem_t *decalsystem = &ent->decalsystem;
10626         int numdecals;
10627         tridecal_t *decal;
10628         float faderate;
10629         float alpha;
10630         float *v3f;
10631         float *c4f;
10632         float *t2f;
10633         const int *e;
10634         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10635         int numtris = 0;
10636
10637         numdecals = decalsystem->numdecals;
10638         if (!numdecals)
10639                 return;
10640
10641         if (r_showsurfaces.integer)
10642                 return;
10643
10644         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10645         {
10646                 R_DecalSystem_Reset(decalsystem);
10647                 return;
10648         }
10649
10650         // if the model is static it doesn't matter what value we give for
10651         // wantnormals and wanttangents, so this logic uses only rules applicable
10652         // to a model, knowing that they are meaningless otherwise
10653         if (ent == r_refdef.scene.worldentity)
10654                 RSurf_ActiveWorldEntity();
10655         else
10656                 RSurf_ActiveModelEntity(ent, false, false, false);
10657
10658         decalsystem->lastupdatetime = cl.time;
10659         decal = decalsystem->decals;
10660
10661         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10662
10663         // update vertex positions for animated models
10664         v3f = decalsystem->vertex3f;
10665         c4f = decalsystem->color4f;
10666         t2f = decalsystem->texcoord2f;
10667         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10668         {
10669                 if (!decal->color4f[0][3])
10670                         continue;
10671
10672                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10673                         continue;
10674
10675                 // update color values for fading decals
10676                 if (decal->lived >= cl_decals_time.value)
10677                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10678                 else
10679                         alpha = 1.0f;
10680
10681                 c4f[ 0] = decal->color4f[0][0] * alpha;
10682                 c4f[ 1] = decal->color4f[0][1] * alpha;
10683                 c4f[ 2] = decal->color4f[0][2] * alpha;
10684                 c4f[ 3] = 1;
10685                 c4f[ 4] = decal->color4f[1][0] * alpha;
10686                 c4f[ 5] = decal->color4f[1][1] * alpha;
10687                 c4f[ 6] = decal->color4f[1][2] * alpha;
10688                 c4f[ 7] = 1;
10689                 c4f[ 8] = decal->color4f[2][0] * alpha;
10690                 c4f[ 9] = decal->color4f[2][1] * alpha;
10691                 c4f[10] = decal->color4f[2][2] * alpha;
10692                 c4f[11] = 1;
10693
10694                 t2f[0] = decal->texcoord2f[0][0];
10695                 t2f[1] = decal->texcoord2f[0][1];
10696                 t2f[2] = decal->texcoord2f[1][0];
10697                 t2f[3] = decal->texcoord2f[1][1];
10698                 t2f[4] = decal->texcoord2f[2][0];
10699                 t2f[5] = decal->texcoord2f[2][1];
10700
10701                 // update vertex positions for animated models
10702                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10703                 {
10704                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10705                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10706                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10707                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10708                 }
10709                 else
10710                 {
10711                         VectorCopy(decal->vertex3f[0], v3f);
10712                         VectorCopy(decal->vertex3f[1], v3f + 3);
10713                         VectorCopy(decal->vertex3f[2], v3f + 6);
10714                 }
10715
10716                 if (r_refdef.fogenabled)
10717                 {
10718                         alpha = RSurf_FogVertex(v3f);
10719                         VectorScale(c4f, alpha, c4f);
10720                         alpha = RSurf_FogVertex(v3f + 3);
10721                         VectorScale(c4f + 4, alpha, c4f + 4);
10722                         alpha = RSurf_FogVertex(v3f + 6);
10723                         VectorScale(c4f + 8, alpha, c4f + 8);
10724                 }
10725
10726                 v3f += 9;
10727                 c4f += 12;
10728                 t2f += 6;
10729                 numtris++;
10730         }
10731
10732         if (numtris > 0)
10733         {
10734                 r_refdef.stats.drawndecals += numtris;
10735
10736                 // now render the decals all at once
10737                 // (this assumes they all use one particle font texture!)
10738                 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);
10739 //              R_Mesh_ResetTextureState();
10740                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10741                 GL_DepthMask(false);
10742                 GL_DepthRange(0, 1);
10743                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10744                 GL_DepthTest(true);
10745                 GL_CullFace(GL_NONE);
10746                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10747                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10748                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10749         }
10750 }
10751
10752 static void R_DrawModelDecals(void)
10753 {
10754         int i, numdecals;
10755
10756         // fade faster when there are too many decals
10757         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10758         for (i = 0;i < r_refdef.scene.numentities;i++)
10759                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10760
10761         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10762         for (i = 0;i < r_refdef.scene.numentities;i++)
10763                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10764                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10765
10766         R_DecalSystem_ApplySplatEntitiesQueue();
10767
10768         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10769         for (i = 0;i < r_refdef.scene.numentities;i++)
10770                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10771
10772         r_refdef.stats.totaldecals += numdecals;
10773
10774         if (r_showsurfaces.integer)
10775                 return;
10776
10777         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10778
10779         for (i = 0;i < r_refdef.scene.numentities;i++)
10780         {
10781                 if (!r_refdef.viewcache.entityvisible[i])
10782                         continue;
10783                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10784                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10785         }
10786 }
10787
10788 extern cvar_t mod_collision_bih;
10789 void R_DrawDebugModel(void)
10790 {
10791         entity_render_t *ent = rsurface.entity;
10792         int i, j, k, l, flagsmask;
10793         const msurface_t *surface;
10794         dp_model_t *model = ent->model;
10795         vec3_t v;
10796
10797         switch(vid.renderpath)
10798         {
10799         case RENDERPATH_GL11:
10800         case RENDERPATH_GL13:
10801         case RENDERPATH_GL20:
10802                 break;
10803         case RENDERPATH_D3D9:
10804                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10805                 return;
10806         case RENDERPATH_D3D10:
10807                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10808                 return;
10809         case RENDERPATH_D3D11:
10810                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10811                 return;
10812         case RENDERPATH_SOFT:
10813                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10814                 return;
10815         case RENDERPATH_GLES2:
10816                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10817                 return;
10818         }
10819
10820         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10821
10822 //      R_Mesh_ResetTextureState();
10823         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10824         GL_DepthRange(0, 1);
10825         GL_DepthTest(!r_showdisabledepthtest.integer);
10826         GL_DepthMask(false);
10827         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10828
10829         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10830         {
10831                 int triangleindex;
10832                 int bihleafindex;
10833                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10834                 const q3mbrush_t *brush;
10835                 const bih_t *bih = &model->collision_bih;
10836                 const bih_leaf_t *bihleaf;
10837                 float vertex3f[3][3];
10838                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10839                 cullbox = false;
10840                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10841                 {
10842                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10843                                 continue;
10844                         switch (bihleaf->type)
10845                         {
10846                         case BIH_BRUSH:
10847                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10848                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10849                                 {
10850                                         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);
10851                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10852                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10853                                 }
10854                                 break;
10855                         case BIH_COLLISIONTRIANGLE:
10856                                 triangleindex = bihleaf->itemindex;
10857                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10858                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10859                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10860                                 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);
10861                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10862                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10863                                 break;
10864                         case BIH_RENDERTRIANGLE:
10865                                 triangleindex = bihleaf->itemindex;
10866                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10867                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10868                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10869                                 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);
10870                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10871                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10872                                 break;
10873                         }
10874                 }
10875         }
10876
10877         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10878
10879         if (r_showtris.integer || (r_shownormals.value != 0))
10880         {
10881                 if (r_showdisabledepthtest.integer)
10882                 {
10883                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10884                         GL_DepthMask(false);
10885                 }
10886                 else
10887                 {
10888                         GL_BlendFunc(GL_ONE, GL_ZERO);
10889                         GL_DepthMask(true);
10890                 }
10891                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10892                 {
10893                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10894                                 continue;
10895                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10896                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10897                         {
10898                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10899                                 if (r_showtris.value > 0)
10900                                 {
10901                                         if (!rsurface.texture->currentlayers->depthmask)
10902                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10903                                         else if (ent == r_refdef.scene.worldentity)
10904                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10905                                         else
10906                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10907                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10908                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10909                                         RSurf_DrawBatch();
10910                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10911                                         CHECKGLERROR
10912                                 }
10913                                 if (r_shownormals.value < 0)
10914                                 {
10915                                         qglBegin(GL_LINES);
10916                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10917                                         {
10918                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10919                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10920                                                 qglVertex3f(v[0], v[1], v[2]);
10921                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10922                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10923                                                 qglVertex3f(v[0], v[1], v[2]);
10924                                         }
10925                                         qglEnd();
10926                                         CHECKGLERROR
10927                                 }
10928                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10929                                 {
10930                                         qglBegin(GL_LINES);
10931                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10932                                         {
10933                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10934                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10935                                                 qglVertex3f(v[0], v[1], v[2]);
10936                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10937                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10938                                                 qglVertex3f(v[0], v[1], v[2]);
10939                                         }
10940                                         qglEnd();
10941                                         CHECKGLERROR
10942                                         qglBegin(GL_LINES);
10943                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10944                                         {
10945                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10946                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10947                                                 qglVertex3f(v[0], v[1], v[2]);
10948                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10949                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10950                                                 qglVertex3f(v[0], v[1], v[2]);
10951                                         }
10952                                         qglEnd();
10953                                         CHECKGLERROR
10954                                         qglBegin(GL_LINES);
10955                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10956                                         {
10957                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10958                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10959                                                 qglVertex3f(v[0], v[1], v[2]);
10960                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10961                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10962                                                 qglVertex3f(v[0], v[1], v[2]);
10963                                         }
10964                                         qglEnd();
10965                                         CHECKGLERROR
10966                                 }
10967                         }
10968                 }
10969                 rsurface.texture = NULL;
10970         }
10971 }
10972
10973 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10974 int r_maxsurfacelist = 0;
10975 const msurface_t **r_surfacelist = NULL;
10976 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10977 {
10978         int i, j, endj, flagsmask;
10979         dp_model_t *model = r_refdef.scene.worldmodel;
10980         msurface_t *surfaces;
10981         unsigned char *update;
10982         int numsurfacelist = 0;
10983         if (model == NULL)
10984                 return;
10985
10986         if (r_maxsurfacelist < model->num_surfaces)
10987         {
10988                 r_maxsurfacelist = model->num_surfaces;
10989                 if (r_surfacelist)
10990                         Mem_Free((msurface_t**)r_surfacelist);
10991                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
10992         }
10993
10994         RSurf_ActiveWorldEntity();
10995
10996         surfaces = model->data_surfaces;
10997         update = model->brushq1.lightmapupdateflags;
10998
10999         // update light styles on this submodel
11000         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11001         {
11002                 model_brush_lightstyleinfo_t *style;
11003                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11004                 {
11005                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11006                         {
11007                                 int *list = style->surfacelist;
11008                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11009                                 for (j = 0;j < style->numsurfaces;j++)
11010                                         update[list[j]] = true;
11011                         }
11012                 }
11013         }
11014
11015         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11016
11017         if (debug)
11018         {
11019                 R_DrawDebugModel();
11020                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11021                 return;
11022         }
11023
11024         rsurface.lightmaptexture = NULL;
11025         rsurface.deluxemaptexture = NULL;
11026         rsurface.uselightmaptexture = false;
11027         rsurface.texture = NULL;
11028         rsurface.rtlight = NULL;
11029         numsurfacelist = 0;
11030         // add visible surfaces to draw list
11031         for (i = 0;i < model->nummodelsurfaces;i++)
11032         {
11033                 j = model->sortedmodelsurfaces[i];
11034                 if (r_refdef.viewcache.world_surfacevisible[j])
11035                         r_surfacelist[numsurfacelist++] = surfaces + j;
11036         }
11037         // update lightmaps if needed
11038         if (model->brushq1.firstrender)
11039         {
11040                 model->brushq1.firstrender = false;
11041                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11042                         if (update[j])
11043                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11044         }
11045         else if (update)
11046         {
11047                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11048                         if (r_refdef.viewcache.world_surfacevisible[j])
11049                                 if (update[j])
11050                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11051         }
11052         // don't do anything if there were no surfaces
11053         if (!numsurfacelist)
11054         {
11055                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11056                 return;
11057         }
11058         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11059
11060         // add to stats if desired
11061         if (r_speeds.integer && !skysurfaces && !depthonly)
11062         {
11063                 r_refdef.stats.world_surfaces += numsurfacelist;
11064                 for (j = 0;j < numsurfacelist;j++)
11065                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11066         }
11067
11068         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11069 }
11070
11071 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11072 {
11073         int i, j, endj, flagsmask;
11074         dp_model_t *model = ent->model;
11075         msurface_t *surfaces;
11076         unsigned char *update;
11077         int numsurfacelist = 0;
11078         if (model == NULL)
11079                 return;
11080
11081         if (r_maxsurfacelist < model->num_surfaces)
11082         {
11083                 r_maxsurfacelist = model->num_surfaces;
11084                 if (r_surfacelist)
11085                         Mem_Free((msurface_t **)r_surfacelist);
11086                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11087         }
11088
11089         // if the model is static it doesn't matter what value we give for
11090         // wantnormals and wanttangents, so this logic uses only rules applicable
11091         // to a model, knowing that they are meaningless otherwise
11092         if (ent == r_refdef.scene.worldentity)
11093                 RSurf_ActiveWorldEntity();
11094         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11095                 RSurf_ActiveModelEntity(ent, false, false, false);
11096         else if (prepass)
11097                 RSurf_ActiveModelEntity(ent, true, true, true);
11098         else if (depthonly)
11099         {
11100                 switch (vid.renderpath)
11101                 {
11102                 case RENDERPATH_GL20:
11103                 case RENDERPATH_D3D9:
11104                 case RENDERPATH_D3D10:
11105                 case RENDERPATH_D3D11:
11106                 case RENDERPATH_SOFT:
11107                 case RENDERPATH_GLES2:
11108                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11109                         break;
11110                 case RENDERPATH_GL13:
11111                 case RENDERPATH_GL11:
11112                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11113                         break;
11114                 }
11115         }
11116         else
11117         {
11118                 switch (vid.renderpath)
11119                 {
11120                 case RENDERPATH_GL20:
11121                 case RENDERPATH_D3D9:
11122                 case RENDERPATH_D3D10:
11123                 case RENDERPATH_D3D11:
11124                 case RENDERPATH_SOFT:
11125                 case RENDERPATH_GLES2:
11126                         RSurf_ActiveModelEntity(ent, true, true, false);
11127                         break;
11128                 case RENDERPATH_GL13:
11129                 case RENDERPATH_GL11:
11130                         RSurf_ActiveModelEntity(ent, true, false, false);
11131                         break;
11132                 }
11133         }
11134
11135         surfaces = model->data_surfaces;
11136         update = model->brushq1.lightmapupdateflags;
11137
11138         // update light styles
11139         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11140         {
11141                 model_brush_lightstyleinfo_t *style;
11142                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11143                 {
11144                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11145                         {
11146                                 int *list = style->surfacelist;
11147                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11148                                 for (j = 0;j < style->numsurfaces;j++)
11149                                         update[list[j]] = true;
11150                         }
11151                 }
11152         }
11153
11154         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11155
11156         if (debug)
11157         {
11158                 R_DrawDebugModel();
11159                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11160                 return;
11161         }
11162
11163         rsurface.lightmaptexture = NULL;
11164         rsurface.deluxemaptexture = NULL;
11165         rsurface.uselightmaptexture = false;
11166         rsurface.texture = NULL;
11167         rsurface.rtlight = NULL;
11168         numsurfacelist = 0;
11169         // add visible surfaces to draw list
11170         for (i = 0;i < model->nummodelsurfaces;i++)
11171                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11172         // don't do anything if there were no surfaces
11173         if (!numsurfacelist)
11174         {
11175                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11176                 return;
11177         }
11178         // update lightmaps if needed
11179         if (update)
11180         {
11181                 int updated = 0;
11182                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11183                 {
11184                         if (update[j])
11185                         {
11186                                 updated++;
11187                                 R_BuildLightMap(ent, surfaces + j);
11188                         }
11189                 }
11190         }
11191         if (update)
11192                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11193                         if (update[j])
11194                                 R_BuildLightMap(ent, surfaces + j);
11195         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11196
11197         // add to stats if desired
11198         if (r_speeds.integer && !skysurfaces && !depthonly)
11199         {
11200                 r_refdef.stats.entities_surfaces += numsurfacelist;
11201                 for (j = 0;j < numsurfacelist;j++)
11202                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11203         }
11204
11205         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11206 }
11207
11208 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11209 {
11210         static texture_t texture;
11211         static msurface_t surface;
11212         const msurface_t *surfacelist = &surface;
11213
11214         // fake enough texture and surface state to render this geometry
11215
11216         texture.update_lastrenderframe = -1; // regenerate this texture
11217         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11218         texture.currentskinframe = skinframe;
11219         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11220         texture.offsetmapping = OFFSETMAPPING_OFF;
11221         texture.offsetscale = 1;
11222         texture.specularscalemod = 1;
11223         texture.specularpowermod = 1;
11224
11225         surface.texture = &texture;
11226         surface.num_triangles = numtriangles;
11227         surface.num_firsttriangle = firsttriangle;
11228         surface.num_vertices = numvertices;
11229         surface.num_firstvertex = firstvertex;
11230
11231         // now render it
11232         rsurface.texture = R_GetCurrentTexture(surface.texture);
11233         rsurface.lightmaptexture = NULL;
11234         rsurface.deluxemaptexture = NULL;
11235         rsurface.uselightmaptexture = false;
11236         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11237 }
11238
11239 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)
11240 {
11241         static msurface_t surface;
11242         const msurface_t *surfacelist = &surface;
11243
11244         // fake enough texture and surface state to render this geometry
11245         surface.texture = texture;
11246         surface.num_triangles = numtriangles;
11247         surface.num_firsttriangle = firsttriangle;
11248         surface.num_vertices = numvertices;
11249         surface.num_firstvertex = firstvertex;
11250
11251         // now render it
11252         rsurface.texture = R_GetCurrentTexture(surface.texture);
11253         rsurface.lightmaptexture = NULL;
11254         rsurface.deluxemaptexture = NULL;
11255         rsurface.uselightmaptexture = false;
11256         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11257 }