]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
move glsl/default.glsl embedded file out to its own header file
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
189
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
206
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 #include "shader_glsl.h"
597 ;
598
599 const char *builtinhlslshaderstring =
600 #include "shader_hlsl.h"
601 ;
602
603 char *glslshaderstring = NULL;
604 char *hlslshaderstring = NULL;
605
606 //=======================================================================================================================================================
607
608 typedef struct shaderpermutationinfo_s
609 {
610         const char *pretext;
611         const char *name;
612 }
613 shaderpermutationinfo_t;
614
615 typedef struct shadermodeinfo_s
616 {
617         const char *vertexfilename;
618         const char *geometryfilename;
619         const char *fragmentfilename;
620         const char *pretext;
621         const char *name;
622 }
623 shadermodeinfo_t;
624
625 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
626 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
627 {
628         {"#define USEDIFFUSE\n", " diffuse"},
629         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
630         {"#define USEVIEWTINT\n", " viewtint"},
631         {"#define USECOLORMAPPING\n", " colormapping"},
632         {"#define USESATURATION\n", " saturation"},
633         {"#define USEFOGINSIDE\n", " foginside"},
634         {"#define USEFOGOUTSIDE\n", " fogoutside"},
635         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
636         {"#define USEGAMMARAMPS\n", " gammaramps"},
637         {"#define USECUBEFILTER\n", " cubefilter"},
638         {"#define USEGLOW\n", " glow"},
639         {"#define USEBLOOM\n", " bloom"},
640         {"#define USESPECULAR\n", " specular"},
641         {"#define USEPOSTPROCESSING\n", " postprocessing"},
642         {"#define USEREFLECTION\n", " reflection"},
643         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
644         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
645         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
646         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
647         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
648         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
649         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
650         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
651         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
652         {"#define USEALPHAKILL\n", " alphakill"},
653         {"#define USEREFLECTCUBE\n", " reflectcube"},
654         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
655         {"#define USEBOUNCEGRID\n", " bouncegrid"},
656 };
657
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
660 {
661         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
677 };
678
679 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
680 {
681         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
697 };
698
699 struct r_glsl_permutation_s;
700 typedef struct r_glsl_permutation_s
701 {
702         /// hash lookup data
703         struct r_glsl_permutation_s *hashnext;
704         unsigned int mode;
705         unsigned int permutation;
706
707         /// indicates if we have tried compiling this permutation already
708         qboolean compiled;
709         /// 0 if compilation failed
710         int program;
711         // texture units assigned to each detected uniform
712         int tex_Texture_First;
713         int tex_Texture_Second;
714         int tex_Texture_GammaRamps;
715         int tex_Texture_Normal;
716         int tex_Texture_Color;
717         int tex_Texture_Gloss;
718         int tex_Texture_Glow;
719         int tex_Texture_SecondaryNormal;
720         int tex_Texture_SecondaryColor;
721         int tex_Texture_SecondaryGloss;
722         int tex_Texture_SecondaryGlow;
723         int tex_Texture_Pants;
724         int tex_Texture_Shirt;
725         int tex_Texture_FogHeightTexture;
726         int tex_Texture_FogMask;
727         int tex_Texture_Lightmap;
728         int tex_Texture_Deluxemap;
729         int tex_Texture_Attenuation;
730         int tex_Texture_Cube;
731         int tex_Texture_Refraction;
732         int tex_Texture_Reflection;
733         int tex_Texture_ShadowMap2D;
734         int tex_Texture_CubeProjection;
735         int tex_Texture_ScreenDepth;
736         int tex_Texture_ScreenNormalMap;
737         int tex_Texture_ScreenDiffuse;
738         int tex_Texture_ScreenSpecular;
739         int tex_Texture_ReflectMask;
740         int tex_Texture_ReflectCube;
741         int tex_Texture_BounceGrid;
742         /// locations of detected uniforms in program object, or -1 if not found
743         int loc_Texture_First;
744         int loc_Texture_Second;
745         int loc_Texture_GammaRamps;
746         int loc_Texture_Normal;
747         int loc_Texture_Color;
748         int loc_Texture_Gloss;
749         int loc_Texture_Glow;
750         int loc_Texture_SecondaryNormal;
751         int loc_Texture_SecondaryColor;
752         int loc_Texture_SecondaryGloss;
753         int loc_Texture_SecondaryGlow;
754         int loc_Texture_Pants;
755         int loc_Texture_Shirt;
756         int loc_Texture_FogHeightTexture;
757         int loc_Texture_FogMask;
758         int loc_Texture_Lightmap;
759         int loc_Texture_Deluxemap;
760         int loc_Texture_Attenuation;
761         int loc_Texture_Cube;
762         int loc_Texture_Refraction;
763         int loc_Texture_Reflection;
764         int loc_Texture_ShadowMap2D;
765         int loc_Texture_CubeProjection;
766         int loc_Texture_ScreenDepth;
767         int loc_Texture_ScreenNormalMap;
768         int loc_Texture_ScreenDiffuse;
769         int loc_Texture_ScreenSpecular;
770         int loc_Texture_ReflectMask;
771         int loc_Texture_ReflectCube;
772         int loc_Texture_BounceGrid;
773         int loc_Alpha;
774         int loc_BloomBlur_Parameters;
775         int loc_ClientTime;
776         int loc_Color_Ambient;
777         int loc_Color_Diffuse;
778         int loc_Color_Specular;
779         int loc_Color_Glow;
780         int loc_Color_Pants;
781         int loc_Color_Shirt;
782         int loc_DeferredColor_Ambient;
783         int loc_DeferredColor_Diffuse;
784         int loc_DeferredColor_Specular;
785         int loc_DeferredMod_Diffuse;
786         int loc_DeferredMod_Specular;
787         int loc_DistortScaleRefractReflect;
788         int loc_EyePosition;
789         int loc_FogColor;
790         int loc_FogHeightFade;
791         int loc_FogPlane;
792         int loc_FogPlaneViewDist;
793         int loc_FogRangeRecip;
794         int loc_LightColor;
795         int loc_LightDir;
796         int loc_LightPosition;
797         int loc_OffsetMapping_Scale;
798         int loc_PixelSize;
799         int loc_ReflectColor;
800         int loc_ReflectFactor;
801         int loc_ReflectOffset;
802         int loc_RefractColor;
803         int loc_Saturation;
804         int loc_ScreenCenterRefractReflect;
805         int loc_ScreenScaleRefractReflect;
806         int loc_ScreenToDepth;
807         int loc_ShadowMap_Parameters;
808         int loc_ShadowMap_TextureScale;
809         int loc_SpecularPower;
810         int loc_UserVec1;
811         int loc_UserVec2;
812         int loc_UserVec3;
813         int loc_UserVec4;
814         int loc_ViewTintColor;
815         int loc_ViewToLight;
816         int loc_ModelToLight;
817         int loc_TexMatrix;
818         int loc_BackgroundTexMatrix;
819         int loc_ModelViewProjectionMatrix;
820         int loc_ModelViewMatrix;
821         int loc_PixelToScreenTexCoord;
822         int loc_ModelToReflectCube;
823         int loc_ShadowMapMatrix;
824         int loc_BloomColorSubtract;
825         int loc_NormalmapScrollBlend;
826         int loc_BounceGridMatrix;
827         int loc_BounceGridIntensity;
828 }
829 r_glsl_permutation_t;
830
831 #define SHADERPERMUTATION_HASHSIZE 256
832
833
834 // non-degradable "lightweight" shader parameters to keep the permutations simpler
835 // these can NOT degrade! only use for simple stuff
836 enum
837 {
838         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
839         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
840         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
841         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
842         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
843         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
844 };
845 #define SHADERSTATICPARMS_COUNT 6
846
847 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
848 static int shaderstaticparms_count = 0;
849
850 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
851 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
852 qboolean R_CompileShader_CheckStaticParms(void)
853 {
854         static int r_compileshader_staticparms_save[1];
855         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
856         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
857
858         // detect all
859         if (r_glsl_saturation_redcompensate.integer)
860                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
861         if (r_shadow_glossexact.integer)
862                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
863         if (r_glsl_postprocess.integer)
864         {
865                 if (r_glsl_postprocess_uservec1_enable.integer)
866                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
867                 if (r_glsl_postprocess_uservec2_enable.integer)
868                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
869                 if (r_glsl_postprocess_uservec3_enable.integer)
870                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
871                 if (r_glsl_postprocess_uservec4_enable.integer)
872                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
873         }
874         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
875 }
876
877 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
878         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
879                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
880         else \
881                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
882 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
883 {
884         shaderstaticparms_count = 0;
885
886         // emit all
887         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
888         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
889         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
893 }
894
895 /// information about each possible shader permutation
896 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
897 /// currently selected permutation
898 r_glsl_permutation_t *r_glsl_permutation;
899 /// storage for permutations linked in the hash table
900 memexpandablearray_t r_glsl_permutationarray;
901
902 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
903 {
904         //unsigned int hashdepth = 0;
905         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
906         r_glsl_permutation_t *p;
907         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
908         {
909                 if (p->mode == mode && p->permutation == permutation)
910                 {
911                         //if (hashdepth > 10)
912                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
913                         return p;
914                 }
915                 //hashdepth++;
916         }
917         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
918         p->mode = mode;
919         p->permutation = permutation;
920         p->hashnext = r_glsl_permutationhash[mode][hashindex];
921         r_glsl_permutationhash[mode][hashindex] = p;
922         //if (hashdepth > 10)
923         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
924         return p;
925 }
926
927 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
928 {
929         char *shaderstring;
930         if (!filename || !filename[0])
931                 return NULL;
932         if (!strcmp(filename, "glsl/default.glsl"))
933         {
934                 if (!glslshaderstring)
935                 {
936                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
937                         if (glslshaderstring)
938                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
939                         else
940                                 glslshaderstring = (char *)builtinshaderstring;
941                 }
942                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
943                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
944                 return shaderstring;
945         }
946         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
947         if (shaderstring)
948         {
949                 if (printfromdisknotice)
950                         Con_DPrintf("from disk %s... ", filename);
951                 return shaderstring;
952         }
953         return shaderstring;
954 }
955
956 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
957 {
958         int i;
959         int sampler;
960         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
961         char *vertexstring, *geometrystring, *fragmentstring;
962         char permutationname[256];
963         int vertstrings_count = 0;
964         int geomstrings_count = 0;
965         int fragstrings_count = 0;
966         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
967         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969
970         if (p->compiled)
971                 return;
972         p->compiled = true;
973         p->program = 0;
974
975         permutationname[0] = 0;
976         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
977         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
978         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
979
980         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
981
982         // the first pretext is which type of shader to compile as
983         // (later these will all be bound together as a program object)
984         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
985         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
986         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
987
988         // the second pretext is the mode (for example a light source)
989         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
990         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
991         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
992         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
993
994         // now add all the permutation pretexts
995         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
996         {
997                 if (permutation & (1<<i))
998                 {
999                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1000                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1001                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1002                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1003                 }
1004                 else
1005                 {
1006                         // keep line numbers correct
1007                         vertstrings_list[vertstrings_count++] = "\n";
1008                         geomstrings_list[geomstrings_count++] = "\n";
1009                         fragstrings_list[fragstrings_count++] = "\n";
1010                 }
1011         }
1012
1013         // add static parms
1014         R_CompileShader_AddStaticParms(mode, permutation);
1015         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1016         vertstrings_count += shaderstaticparms_count;
1017         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1018         geomstrings_count += shaderstaticparms_count;
1019         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1020         fragstrings_count += shaderstaticparms_count;
1021
1022         // now append the shader text itself
1023         vertstrings_list[vertstrings_count++] = vertexstring;
1024         geomstrings_list[geomstrings_count++] = geometrystring;
1025         fragstrings_list[fragstrings_count++] = fragmentstring;
1026
1027         // if any sources were NULL, clear the respective list
1028         if (!vertexstring)
1029                 vertstrings_count = 0;
1030         if (!geometrystring)
1031                 geomstrings_count = 0;
1032         if (!fragmentstring)
1033                 fragstrings_count = 0;
1034
1035         // compile the shader program
1036         if (vertstrings_count + geomstrings_count + fragstrings_count)
1037                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1038         if (p->program)
1039         {
1040                 CHECKGLERROR
1041                 qglUseProgram(p->program);CHECKGLERROR
1042                 // look up all the uniform variable names we care about, so we don't
1043                 // have to look them up every time we set them
1044
1045                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1046                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1047                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1048                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1049                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1050                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1051                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1052                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1053                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1054                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1055                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1056                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1057                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1058                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1059                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1060                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1061                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1062                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1063                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1064                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1065                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1066                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1067                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1068                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1069                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1070                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1071                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1072                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1073                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1074                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1075                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1076                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1077                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1078                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1079                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1080                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1081                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1082                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1083                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1084                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1085                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1086                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1087                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1088                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1089                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1090                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1091                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1092                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1093                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1094                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1095                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1096                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1097                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1098                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1099                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1100                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1101                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1102                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1103                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1104                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1105                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1106                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1107                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1108                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1109                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1110                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1111                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1112                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1113                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1114                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1115                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1116                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1117                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1118                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1119                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1120                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1121                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1122                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1123                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1124                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1125                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1126                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1127                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1128                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1129                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1130                 // initialize the samplers to refer to the texture units we use
1131                 p->tex_Texture_First = -1;
1132                 p->tex_Texture_Second = -1;
1133                 p->tex_Texture_GammaRamps = -1;
1134                 p->tex_Texture_Normal = -1;
1135                 p->tex_Texture_Color = -1;
1136                 p->tex_Texture_Gloss = -1;
1137                 p->tex_Texture_Glow = -1;
1138                 p->tex_Texture_SecondaryNormal = -1;
1139                 p->tex_Texture_SecondaryColor = -1;
1140                 p->tex_Texture_SecondaryGloss = -1;
1141                 p->tex_Texture_SecondaryGlow = -1;
1142                 p->tex_Texture_Pants = -1;
1143                 p->tex_Texture_Shirt = -1;
1144                 p->tex_Texture_FogHeightTexture = -1;
1145                 p->tex_Texture_FogMask = -1;
1146                 p->tex_Texture_Lightmap = -1;
1147                 p->tex_Texture_Deluxemap = -1;
1148                 p->tex_Texture_Attenuation = -1;
1149                 p->tex_Texture_Cube = -1;
1150                 p->tex_Texture_Refraction = -1;
1151                 p->tex_Texture_Reflection = -1;
1152                 p->tex_Texture_ShadowMap2D = -1;
1153                 p->tex_Texture_CubeProjection = -1;
1154                 p->tex_Texture_ScreenDepth = -1;
1155                 p->tex_Texture_ScreenNormalMap = -1;
1156                 p->tex_Texture_ScreenDiffuse = -1;
1157                 p->tex_Texture_ScreenSpecular = -1;
1158                 p->tex_Texture_ReflectMask = -1;
1159                 p->tex_Texture_ReflectCube = -1;
1160                 p->tex_Texture_BounceGrid = -1;
1161                 sampler = 0;
1162                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1163                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1164                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1165                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1166                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1167                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1168                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1169                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1170                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1171                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1172                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1173                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1174                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1175                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1176                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1177                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1178                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1179                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1180                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1181                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1182                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1183                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1184                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1185                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1186                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1187                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1188                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1189                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1190                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1191                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1192                 CHECKGLERROR
1193                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1194         }
1195         else
1196                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1197
1198         // free the strings
1199         if (vertexstring)
1200                 Mem_Free(vertexstring);
1201         if (geometrystring)
1202                 Mem_Free(geometrystring);
1203         if (fragmentstring)
1204                 Mem_Free(fragmentstring);
1205 }
1206
1207 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1208 {
1209         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1210         if (r_glsl_permutation != perm)
1211         {
1212                 r_glsl_permutation = perm;
1213                 if (!r_glsl_permutation->program)
1214                 {
1215                         if (!r_glsl_permutation->compiled)
1216                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1217                         if (!r_glsl_permutation->program)
1218                         {
1219                                 // remove features until we find a valid permutation
1220                                 int i;
1221                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1222                                 {
1223                                         // reduce i more quickly whenever it would not remove any bits
1224                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1225                                         if (!(permutation & j))
1226                                                 continue;
1227                                         permutation -= j;
1228                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1229                                         if (!r_glsl_permutation->compiled)
1230                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1231                                         if (r_glsl_permutation->program)
1232                                                 break;
1233                                 }
1234                                 if (i >= SHADERPERMUTATION_COUNT)
1235                                 {
1236                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1237                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238                                         qglUseProgram(0);CHECKGLERROR
1239                                         return; // no bit left to clear, entire mode is broken
1240                                 }
1241                         }
1242                 }
1243                 CHECKGLERROR
1244                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1245         }
1246         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1247         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1248         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1249 }
1250
1251 #ifdef SUPPORTD3D
1252
1253 #ifdef SUPPORTD3D
1254 #include <d3d9.h>
1255 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1256 extern D3DCAPS9 vid_d3d9caps;
1257 #endif
1258
1259 struct r_hlsl_permutation_s;
1260 typedef struct r_hlsl_permutation_s
1261 {
1262         /// hash lookup data
1263         struct r_hlsl_permutation_s *hashnext;
1264         unsigned int mode;
1265         unsigned int permutation;
1266
1267         /// indicates if we have tried compiling this permutation already
1268         qboolean compiled;
1269         /// NULL if compilation failed
1270         IDirect3DVertexShader9 *vertexshader;
1271         IDirect3DPixelShader9 *pixelshader;
1272 }
1273 r_hlsl_permutation_t;
1274
1275 typedef enum D3DVSREGISTER_e
1276 {
1277         D3DVSREGISTER_TexMatrix = 0, // float4x4
1278         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1279         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1280         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1281         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1282         D3DVSREGISTER_ModelToLight = 20, // float4x4
1283         D3DVSREGISTER_EyePosition = 24,
1284         D3DVSREGISTER_FogPlane = 25,
1285         D3DVSREGISTER_LightDir = 26,
1286         D3DVSREGISTER_LightPosition = 27,
1287 }
1288 D3DVSREGISTER_t;
1289
1290 typedef enum D3DPSREGISTER_e
1291 {
1292         D3DPSREGISTER_Alpha = 0,
1293         D3DPSREGISTER_BloomBlur_Parameters = 1,
1294         D3DPSREGISTER_ClientTime = 2,
1295         D3DPSREGISTER_Color_Ambient = 3,
1296         D3DPSREGISTER_Color_Diffuse = 4,
1297         D3DPSREGISTER_Color_Specular = 5,
1298         D3DPSREGISTER_Color_Glow = 6,
1299         D3DPSREGISTER_Color_Pants = 7,
1300         D3DPSREGISTER_Color_Shirt = 8,
1301         D3DPSREGISTER_DeferredColor_Ambient = 9,
1302         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1303         D3DPSREGISTER_DeferredColor_Specular = 11,
1304         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1305         D3DPSREGISTER_DeferredMod_Specular = 13,
1306         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1307         D3DPSREGISTER_EyePosition = 15, // unused
1308         D3DPSREGISTER_FogColor = 16,
1309         D3DPSREGISTER_FogHeightFade = 17,
1310         D3DPSREGISTER_FogPlane = 18,
1311         D3DPSREGISTER_FogPlaneViewDist = 19,
1312         D3DPSREGISTER_FogRangeRecip = 20,
1313         D3DPSREGISTER_LightColor = 21,
1314         D3DPSREGISTER_LightDir = 22, // unused
1315         D3DPSREGISTER_LightPosition = 23,
1316         D3DPSREGISTER_OffsetMapping_Scale = 24,
1317         D3DPSREGISTER_PixelSize = 25,
1318         D3DPSREGISTER_ReflectColor = 26,
1319         D3DPSREGISTER_ReflectFactor = 27,
1320         D3DPSREGISTER_ReflectOffset = 28,
1321         D3DPSREGISTER_RefractColor = 29,
1322         D3DPSREGISTER_Saturation = 30,
1323         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1324         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1325         D3DPSREGISTER_ScreenToDepth = 33,
1326         D3DPSREGISTER_ShadowMap_Parameters = 34,
1327         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1328         D3DPSREGISTER_SpecularPower = 36,
1329         D3DPSREGISTER_UserVec1 = 37,
1330         D3DPSREGISTER_UserVec2 = 38,
1331         D3DPSREGISTER_UserVec3 = 39,
1332         D3DPSREGISTER_UserVec4 = 40,
1333         D3DPSREGISTER_ViewTintColor = 41,
1334         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1335         D3DPSREGISTER_BloomColorSubtract = 43,
1336         D3DPSREGISTER_ViewToLight = 44, // float4x4
1337         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1338         D3DPSREGISTER_NormalmapScrollBlend = 52,
1339         // next at 53
1340 }
1341 D3DPSREGISTER_t;
1342
1343 /// information about each possible shader permutation
1344 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1345 /// currently selected permutation
1346 r_hlsl_permutation_t *r_hlsl_permutation;
1347 /// storage for permutations linked in the hash table
1348 memexpandablearray_t r_hlsl_permutationarray;
1349
1350 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1351 {
1352         //unsigned int hashdepth = 0;
1353         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1354         r_hlsl_permutation_t *p;
1355         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1356         {
1357                 if (p->mode == mode && p->permutation == permutation)
1358                 {
1359                         //if (hashdepth > 10)
1360                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1361                         return p;
1362                 }
1363                 //hashdepth++;
1364         }
1365         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1366         p->mode = mode;
1367         p->permutation = permutation;
1368         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1369         r_hlsl_permutationhash[mode][hashindex] = p;
1370         //if (hashdepth > 10)
1371         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1372         return p;
1373 }
1374
1375 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1376 {
1377         char *shaderstring;
1378         if (!filename || !filename[0])
1379                 return NULL;
1380         if (!strcmp(filename, "hlsl/default.hlsl"))
1381         {
1382                 if (!hlslshaderstring)
1383                 {
1384                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1385                         if (hlslshaderstring)
1386                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1387                         else
1388                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1389                 }
1390                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1391                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1392                 return shaderstring;
1393         }
1394         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1395         if (shaderstring)
1396         {
1397                 if (printfromdisknotice)
1398                         Con_DPrintf("from disk %s... ", filename);
1399                 return shaderstring;
1400         }
1401         return shaderstring;
1402 }
1403
1404 #include <d3dx9.h>
1405 //#include <d3dx9shader.h>
1406 //#include <d3dx9mesh.h>
1407
1408 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1409 {
1410         DWORD *vsbin = NULL;
1411         DWORD *psbin = NULL;
1412         fs_offset_t vsbinsize;
1413         fs_offset_t psbinsize;
1414 //      IDirect3DVertexShader9 *vs = NULL;
1415 //      IDirect3DPixelShader9 *ps = NULL;
1416         ID3DXBuffer *vslog = NULL;
1417         ID3DXBuffer *vsbuffer = NULL;
1418         ID3DXConstantTable *vsconstanttable = NULL;
1419         ID3DXBuffer *pslog = NULL;
1420         ID3DXBuffer *psbuffer = NULL;
1421         ID3DXConstantTable *psconstanttable = NULL;
1422         int vsresult = 0;
1423         int psresult = 0;
1424         char temp[MAX_INPUTLINE];
1425         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1426         qboolean debugshader = gl_paranoid.integer != 0;
1427         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1428         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1429         if (!debugshader)
1430         {
1431                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1432                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1433         }
1434         if ((!vsbin && vertstring) || (!psbin && fragstring))
1435         {
1436                 const char* dllnames_d3dx9 [] =
1437                 {
1438                         "d3dx9_43.dll",
1439                         "d3dx9_42.dll",
1440                         "d3dx9_41.dll",
1441                         "d3dx9_40.dll",
1442                         "d3dx9_39.dll",
1443                         "d3dx9_38.dll",
1444                         "d3dx9_37.dll",
1445                         "d3dx9_36.dll",
1446                         "d3dx9_35.dll",
1447                         "d3dx9_34.dll",
1448                         "d3dx9_33.dll",
1449                         "d3dx9_32.dll",
1450                         "d3dx9_31.dll",
1451                         "d3dx9_30.dll",
1452                         "d3dx9_29.dll",
1453                         "d3dx9_28.dll",
1454                         "d3dx9_27.dll",
1455                         "d3dx9_26.dll",
1456                         "d3dx9_25.dll",
1457                         "d3dx9_24.dll",
1458                         NULL
1459                 };
1460                 dllhandle_t d3dx9_dll = NULL;
1461                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1462                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1463                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1464                 dllfunction_t d3dx9_dllfuncs[] =
1465                 {
1466                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1467                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1468                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1469                         {NULL, NULL}
1470                 };
1471                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1472                 {
1473                         DWORD shaderflags = 0;
1474                         if (debugshader)
1475                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1476                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1477                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1478                         if (vertstring && vertstring[0])
1479                         {
1480                                 if (debugshader)
1481                                 {
1482 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1483 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1484                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1485                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1486                                 }
1487                                 else
1488                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1489                                 if (vsbuffer)
1490                                 {
1491                                         vsbinsize = vsbuffer->GetBufferSize();
1492                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1493                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1494                                         vsbuffer->Release();
1495                                 }
1496                                 if (vslog)
1497                                 {
1498                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1499                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1500                                         vslog->Release();
1501                                 }
1502                         }
1503                         if (fragstring && fragstring[0])
1504                         {
1505                                 if (debugshader)
1506                                 {
1507 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1508 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1509                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1510                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1511                                 }
1512                                 else
1513                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1514                                 if (psbuffer)
1515                                 {
1516                                         psbinsize = psbuffer->GetBufferSize();
1517                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1518                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1519                                         psbuffer->Release();
1520                                 }
1521                                 if (pslog)
1522                                 {
1523                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1524                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1525                                         pslog->Release();
1526                                 }
1527                         }
1528                         Sys_UnloadLibrary(&d3dx9_dll);
1529                 }
1530                 else
1531                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1532         }
1533         if (vsbin && psbin)
1534         {
1535                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1536                 if (FAILED(vsresult))
1537                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1538                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1539                 if (FAILED(psresult))
1540                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1541         }
1542         // free the shader data
1543         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1544         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1545 }
1546
1547 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1548 {
1549         int i;
1550         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1551         int vertstring_length = 0;
1552         int geomstring_length = 0;
1553         int fragstring_length = 0;
1554         char *t;
1555         char *vertexstring, *geometrystring, *fragmentstring;
1556         char *vertstring, *geomstring, *fragstring;
1557         char permutationname[256];
1558         char cachename[256];
1559         int vertstrings_count = 0;
1560         int geomstrings_count = 0;
1561         int fragstrings_count = 0;
1562         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1563         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1565
1566         if (p->compiled)
1567                 return;
1568         p->compiled = true;
1569         p->vertexshader = NULL;
1570         p->pixelshader = NULL;
1571
1572         permutationname[0] = 0;
1573         cachename[0] = 0;
1574         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1575         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1576         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1577
1578         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1579         strlcat(cachename, "hlsl/", sizeof(cachename));
1580
1581         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1582         vertstrings_count = 0;
1583         geomstrings_count = 0;
1584         fragstrings_count = 0;
1585         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1586         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1587         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1588
1589         // the first pretext is which type of shader to compile as
1590         // (later these will all be bound together as a program object)
1591         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1592         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1593         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1594
1595         // the second pretext is the mode (for example a light source)
1596         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1597         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1598         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1599         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1600         strlcat(cachename, modeinfo->name, sizeof(cachename));
1601
1602         // now add all the permutation pretexts
1603         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1604         {
1605                 if (permutation & (1<<i))
1606                 {
1607                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1608                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1609                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1610                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1611                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1612                 }
1613                 else
1614                 {
1615                         // keep line numbers correct
1616                         vertstrings_list[vertstrings_count++] = "\n";
1617                         geomstrings_list[geomstrings_count++] = "\n";
1618                         fragstrings_list[fragstrings_count++] = "\n";
1619                 }
1620         }
1621
1622         // add static parms
1623         R_CompileShader_AddStaticParms(mode, permutation);
1624         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1625         vertstrings_count += shaderstaticparms_count;
1626         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1627         geomstrings_count += shaderstaticparms_count;
1628         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1629         fragstrings_count += shaderstaticparms_count;
1630
1631         // replace spaces in the cachename with _ characters
1632         for (i = 0;cachename[i];i++)
1633                 if (cachename[i] == ' ')
1634                         cachename[i] = '_';
1635
1636         // now append the shader text itself
1637         vertstrings_list[vertstrings_count++] = vertexstring;
1638         geomstrings_list[geomstrings_count++] = geometrystring;
1639         fragstrings_list[fragstrings_count++] = fragmentstring;
1640
1641         // if any sources were NULL, clear the respective list
1642         if (!vertexstring)
1643                 vertstrings_count = 0;
1644         if (!geometrystring)
1645                 geomstrings_count = 0;
1646         if (!fragmentstring)
1647                 fragstrings_count = 0;
1648
1649         vertstring_length = 0;
1650         for (i = 0;i < vertstrings_count;i++)
1651                 vertstring_length += strlen(vertstrings_list[i]);
1652         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1653         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1654                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1655
1656         geomstring_length = 0;
1657         for (i = 0;i < geomstrings_count;i++)
1658                 geomstring_length += strlen(geomstrings_list[i]);
1659         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1660         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1661                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1662
1663         fragstring_length = 0;
1664         for (i = 0;i < fragstrings_count;i++)
1665                 fragstring_length += strlen(fragstrings_list[i]);
1666         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1667         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1668                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1669
1670         // try to load the cached shader, or generate one
1671         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1672
1673         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1674                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1675         else
1676                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1677
1678         // free the strings
1679         if (vertstring)
1680                 Mem_Free(vertstring);
1681         if (geomstring)
1682                 Mem_Free(geomstring);
1683         if (fragstring)
1684                 Mem_Free(fragstring);
1685         if (vertexstring)
1686                 Mem_Free(vertexstring);
1687         if (geometrystring)
1688                 Mem_Free(geometrystring);
1689         if (fragmentstring)
1690                 Mem_Free(fragmentstring);
1691 }
1692
1693 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1694 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1695 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1696 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1697 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1698 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1699
1700 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1701 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1702 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1703 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1704 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1705 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1706
1707 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1708 {
1709         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1710         if (r_hlsl_permutation != perm)
1711         {
1712                 r_hlsl_permutation = perm;
1713                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1714                 {
1715                         if (!r_hlsl_permutation->compiled)
1716                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1717                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1718                         {
1719                                 // remove features until we find a valid permutation
1720                                 int i;
1721                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1722                                 {
1723                                         // reduce i more quickly whenever it would not remove any bits
1724                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1725                                         if (!(permutation & j))
1726                                                 continue;
1727                                         permutation -= j;
1728                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1729                                         if (!r_hlsl_permutation->compiled)
1730                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1731                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1732                                                 break;
1733                                 }
1734                                 if (i >= SHADERPERMUTATION_COUNT)
1735                                 {
1736                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1737                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738                                         return; // no bit left to clear, entire mode is broken
1739                                 }
1740                         }
1741                 }
1742                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1743                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1744         }
1745         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1746         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1747         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1748 }
1749 #endif
1750
1751 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1752 {
1753         DPSOFTRAST_SetShader(mode, permutation);
1754         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1755         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1756         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1757 }
1758
1759 void R_GLSL_Restart_f(void)
1760 {
1761         unsigned int i, limit;
1762         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1763                 Mem_Free(glslshaderstring);
1764         glslshaderstring = NULL;
1765         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1766                 Mem_Free(hlslshaderstring);
1767         hlslshaderstring = NULL;
1768         switch(vid.renderpath)
1769         {
1770         case RENDERPATH_D3D9:
1771 #ifdef SUPPORTD3D
1772                 {
1773                         r_hlsl_permutation_t *p;
1774                         r_hlsl_permutation = NULL;
1775                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1776                         for (i = 0;i < limit;i++)
1777                         {
1778                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1779                                 {
1780                                         if (p->vertexshader)
1781                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1782                                         if (p->pixelshader)
1783                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1784                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1785                                 }
1786                         }
1787                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1788                 }
1789 #endif
1790                 break;
1791         case RENDERPATH_D3D10:
1792                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1793                 break;
1794         case RENDERPATH_D3D11:
1795                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1796                 break;
1797         case RENDERPATH_GL20:
1798         case RENDERPATH_GLES2:
1799                 {
1800                         r_glsl_permutation_t *p;
1801                         r_glsl_permutation = NULL;
1802                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1803                         for (i = 0;i < limit;i++)
1804                         {
1805                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1806                                 {
1807                                         GL_Backend_FreeProgram(p->program);
1808                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1809                                 }
1810                         }
1811                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1812                 }
1813                 break;
1814         case RENDERPATH_GL13:
1815         case RENDERPATH_GL11:
1816                 break;
1817         case RENDERPATH_SOFT:
1818                 break;
1819         }
1820 }
1821
1822 void R_GLSL_DumpShader_f(void)
1823 {
1824         int i;
1825         qfile_t *file;
1826
1827         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1828         if (file)
1829         {
1830                 FS_Print(file, "/* The engine may define the following macros:\n");
1831                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1832                 for (i = 0;i < SHADERMODE_COUNT;i++)
1833                         FS_Print(file, glslshadermodeinfo[i].pretext);
1834                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1835                         FS_Print(file, shaderpermutationinfo[i].pretext);
1836                 FS_Print(file, "*/\n");
1837                 FS_Print(file, builtinshaderstring);
1838                 FS_Close(file);
1839                 Con_Printf("glsl/default.glsl written\n");
1840         }
1841         else
1842                 Con_Printf("failed to write to glsl/default.glsl\n");
1843
1844         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1845         if (file)
1846         {
1847                 FS_Print(file, "/* The engine may define the following macros:\n");
1848                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1849                 for (i = 0;i < SHADERMODE_COUNT;i++)
1850                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1851                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852                         FS_Print(file, shaderpermutationinfo[i].pretext);
1853                 FS_Print(file, "*/\n");
1854                 FS_Print(file, builtinhlslshaderstring);
1855                 FS_Close(file);
1856                 Con_Printf("hlsl/default.hlsl written\n");
1857         }
1858         else
1859                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1860 }
1861
1862 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1863 {
1864         if (!second)
1865                 texturemode = GL_MODULATE;
1866         switch (vid.renderpath)
1867         {
1868         case RENDERPATH_D3D9:
1869 #ifdef SUPPORTD3D
1870                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1871                 R_Mesh_TexBind(GL20TU_FIRST , first );
1872                 R_Mesh_TexBind(GL20TU_SECOND, second);
1873 #endif
1874                 break;
1875         case RENDERPATH_D3D10:
1876                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1877                 break;
1878         case RENDERPATH_D3D11:
1879                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1880                 break;
1881         case RENDERPATH_GL20:
1882         case RENDERPATH_GLES2:
1883                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1884                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1885                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1886                 break;
1887         case RENDERPATH_GL13:
1888                 R_Mesh_TexBind(0, first );
1889                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1890                 R_Mesh_TexBind(1, second);
1891                 if (second)
1892                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1893                 break;
1894         case RENDERPATH_GL11:
1895                 R_Mesh_TexBind(0, first );
1896                 break;
1897         case RENDERPATH_SOFT:
1898                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1899                 R_Mesh_TexBind(GL20TU_FIRST , first );
1900                 R_Mesh_TexBind(GL20TU_SECOND, second);
1901                 break;
1902         }
1903 }
1904
1905 void R_SetupShader_DepthOrShadow(void)
1906 {
1907         switch (vid.renderpath)
1908         {
1909         case RENDERPATH_D3D9:
1910 #ifdef SUPPORTD3D
1911                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1912 #endif
1913                 break;
1914         case RENDERPATH_D3D10:
1915                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916                 break;
1917         case RENDERPATH_D3D11:
1918                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919                 break;
1920         case RENDERPATH_GL20:
1921         case RENDERPATH_GLES2:
1922                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1923                 break;
1924         case RENDERPATH_GL13:
1925                 R_Mesh_TexBind(0, 0);
1926                 R_Mesh_TexBind(1, 0);
1927                 break;
1928         case RENDERPATH_GL11:
1929                 R_Mesh_TexBind(0, 0);
1930                 break;
1931         case RENDERPATH_SOFT:
1932                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1933                 break;
1934         }
1935 }
1936
1937 void R_SetupShader_ShowDepth(void)
1938 {
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTHLSL
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1955                 break;
1956         case RENDERPATH_GL13:
1957                 break;
1958         case RENDERPATH_GL11:
1959                 break;
1960         case RENDERPATH_SOFT:
1961                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1962                 break;
1963         }
1964 }
1965
1966 extern qboolean r_shadow_usingdeferredprepass;
1967 extern cvar_t r_shadow_deferred_8bitrange;
1968 extern rtexture_t *r_shadow_attenuationgradienttexture;
1969 extern rtexture_t *r_shadow_attenuation2dtexture;
1970 extern rtexture_t *r_shadow_attenuation3dtexture;
1971 extern qboolean r_shadow_usingshadowmap2d;
1972 extern qboolean r_shadow_usingshadowmaportho;
1973 extern float r_shadow_shadowmap_texturescale[2];
1974 extern float r_shadow_shadowmap_parameters[4];
1975 extern qboolean r_shadow_shadowmapvsdct;
1976 extern qboolean r_shadow_shadowmapsampler;
1977 extern int r_shadow_shadowmappcf;
1978 extern rtexture_t *r_shadow_shadowmap2dtexture;
1979 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1980 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1981 extern matrix4x4_t r_shadow_shadowmapmatrix;
1982 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1983 extern int r_shadow_prepass_width;
1984 extern int r_shadow_prepass_height;
1985 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1986 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1987 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1988 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1989 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1990 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
1991 {
1992         // a blendfunc allows colormod if:
1993         // a) it can never keep the destination pixel invariant, or
1994         // b) it can keep the destination pixel invariant, and still can do so if colormodded
1995         // this is to prevent unintended side effects from colormod
1996
1997         // in formulas:
1998         // IF there is a (s, sa) for which for all (d, da),
1999         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2000         // THEN, for this (s, sa) and all (colormod, d, da):
2001         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
2002         // OBVIOUSLY, this means that
2003         //   s*colormod * src(s*colormod, d, sa, da) = 0
2004         //   dst(s*colormod, d, sa, da)              = 1
2005
2006         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
2007
2008         // main condition to leave dst color invariant:
2009         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2010         //   src == GL_ZERO:
2011         //     s * 0 + d * dst(s, d, sa, da) == d
2012         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2013         //       => colormod is a problem for GL_SRC_COLOR only
2014         //   src == GL_ONE:
2015         //     s + d * dst(s, d, sa, da) == d
2016         //       => s == 0
2017         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2018         //       => colormod is never problematic for these
2019         //   src == GL_SRC_COLOR:
2020         //     s*s + d * dst(s, d, sa, da) == d
2021         //       => s == 0
2022         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2023         //       => colormod is never problematic for these
2024         //   src == GL_ONE_MINUS_SRC_COLOR:
2025         //     s*(1-s) + d * dst(s, d, sa, da) == d
2026         //       => s == 0 or s == 1
2027         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2028         //       => colormod is a problem for GL_SRC_COLOR only
2029         //   src == GL_DST_COLOR
2030         //     s*d + d * dst(s, d, sa, da) == d
2031         //       => s == 1
2032         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2033         //       => colormod is always a problem
2034         //     or
2035         //       => s == 0
2036         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2037         //       => colormod is never problematic for these
2038         //       => BUT, we do not know s! We must assume it is problematic
2039         //       then... except in GL_ONE case, where we know all invariant
2040         //       cases are fine
2041         //   src == GL_ONE_MINUS_DST_COLOR
2042         //     s*(1-d) + d * dst(s, d, sa, da) == d
2043         //       => s == 0 (1-d is impossible to handle for our desired result)
2044         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2045         //       => colormod is never problematic for these
2046         //   src == GL_SRC_ALPHA
2047         //     s*sa + d * dst(s, d, sa, da) == d
2048         //       => s == 0, or sa == 0
2049         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2050         //       => colormod breaks in the case GL_SRC_COLOR only
2051         //   src == GL_ONE_MINUS_SRC_ALPHA
2052         //     s*(1-sa) + d * dst(s, d, sa, da) == d
2053         //       => s == 0, or sa == 1
2054         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2055         //       => colormod breaks in the case GL_SRC_COLOR only
2056         //   src == GL_DST_ALPHA
2057         //     s*da + d * dst(s, d, sa, da) == d
2058         //       => s == 0
2059         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2060         //       => colormod is never problematic for these
2061
2062         switch(src)
2063         {
2064                 case GL_ZERO:
2065                 case GL_ONE_MINUS_SRC_COLOR:
2066                 case GL_SRC_ALPHA:
2067                 case GL_ONE_MINUS_SRC_ALPHA:
2068                         if(dst == GL_SRC_COLOR)
2069                                 return false;
2070                         return true;
2071                 case GL_ONE:
2072                 case GL_SRC_COLOR:
2073                 case GL_ONE_MINUS_DST_COLOR:
2074                 case GL_DST_ALPHA:
2075                 case GL_ONE_MINUS_DST_ALPHA:
2076                         return true;
2077                 case GL_DST_COLOR:
2078                         if(dst == GL_ONE)
2079                                 return true;
2080                         return false;
2081                 default:
2082                         return false;
2083         }
2084 }
2085 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)
2086 {
2087         // select a permutation of the lighting shader appropriate to this
2088         // combination of texture, entity, light source, and fogging, only use the
2089         // minimum features necessary to avoid wasting rendering time in the
2090         // fragment shader on features that are not being used
2091         unsigned int permutation = 0;
2092         unsigned int mode = 0;
2093         qboolean allow_colormod;
2094         static float dummy_colormod[3] = {1, 1, 1};
2095         float *colormod = rsurface.colormod;
2096         float m16f[16];
2097         matrix4x4_t tempmatrix;
2098         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2099         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2100                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2101         if (rsurfacepass == RSURFPASS_BACKGROUND)
2102         {
2103                 // distorted background
2104                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2105                 {
2106                         mode = SHADERMODE_WATER;
2107                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2108                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2109                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2110                         {
2111                                 // this is the right thing to do for wateralpha
2112                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2113                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2114                         }
2115                         else
2116                         {
2117                                 // this is the right thing to do for entity alpha
2118                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120                         }
2121                 }
2122                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2123                 {
2124                         mode = SHADERMODE_REFRACTION;
2125                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2127                 }
2128                 else
2129                 {
2130                         mode = SHADERMODE_GENERIC;
2131                         permutation |= SHADERPERMUTATION_DIFFUSE;
2132                         GL_BlendFunc(GL_ONE, GL_ZERO);
2133                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2134                 }
2135         }
2136         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2137         {
2138                 if (r_glsl_offsetmapping.integer)
2139                 {
2140                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2141                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2142                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2143                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2144                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2145                         {
2146                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2147                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2148                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2149                         }
2150                 }
2151                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2152                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2153                 // normalmap (deferred prepass), may use alpha test on diffuse
2154                 mode = SHADERMODE_DEFERREDGEOMETRY;
2155                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2156                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2157                 GL_BlendFunc(GL_ONE, GL_ZERO);
2158                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2159         }
2160         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2161         {
2162                 if (r_glsl_offsetmapping.integer)
2163                 {
2164                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2165                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2166                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2167                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2168                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2169                         {
2170                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2171                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2172                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2173                         }
2174                 }
2175                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2176                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2177                 // light source
2178                 mode = SHADERMODE_LIGHTSOURCE;
2179                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2180                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2181                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2182                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2183                 if (diffusescale > 0)
2184                         permutation |= SHADERPERMUTATION_DIFFUSE;
2185                 if (specularscale > 0)
2186                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2187                 if (r_refdef.fogenabled)
2188                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2189                 if (rsurface.texture->colormapping)
2190                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2191                 if (r_shadow_usingshadowmap2d)
2192                 {
2193                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2194                         if(r_shadow_shadowmapvsdct)
2195                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2196
2197                         if (r_shadow_shadowmapsampler)
2198                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2199                         if (r_shadow_shadowmappcf > 1)
2200                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2201                         else if (r_shadow_shadowmappcf)
2202                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2203                 }
2204                 if (rsurface.texture->reflectmasktexture)
2205                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2206                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2207                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
2208         }
2209         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2210         {
2211                 if (r_glsl_offsetmapping.integer)
2212                 {
2213                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2214                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2215                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2216                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2217                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2218                         {
2219                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2220                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2221                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2222                         }
2223                 }
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2225                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2226                 // unshaded geometry (fullbright or ambient model lighting)
2227                 mode = SHADERMODE_FLATCOLOR;
2228                 ambientscale = diffusescale = specularscale = 0;
2229                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2230                         permutation |= SHADERPERMUTATION_GLOW;
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 (rsurface.texture->reflectmasktexture)
2250                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2251                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2252                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2253         }
2254         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2255         {
2256                 if (r_glsl_offsetmapping.integer)
2257                 {
2258                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2259                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2260                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2261                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2262                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2263                         {
2264                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2265                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2266                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2267                         }
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271                 // directional model lighting
2272                 mode = SHADERMODE_LIGHTDIRECTION;
2273                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2274                         permutation |= SHADERPERMUTATION_GLOW;
2275                 permutation |= SHADERPERMUTATION_DIFFUSE;
2276                 if (specularscale > 0)
2277                         permutation |= SHADERPERMUTATION_SPECULAR;
2278                 if (r_refdef.fogenabled)
2279                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2280                 if (rsurface.texture->colormapping)
2281                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2282                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2283                 {
2284                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2285                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2286
2287                         if (r_shadow_shadowmapsampler)
2288                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2289                         if (r_shadow_shadowmappcf > 1)
2290                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2291                         else if (r_shadow_shadowmappcf)
2292                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2293                 }
2294                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2295                         permutation |= SHADERPERMUTATION_REFLECTION;
2296                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2297                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2298                 if (rsurface.texture->reflectmasktexture)
2299                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2300                 if (r_shadow_bouncegridtexture)
2301                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2302                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2303                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304         }
2305         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2306         {
2307                 if (r_glsl_offsetmapping.integer)
2308                 {
2309                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2310                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2311                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2312                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2313                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2314                         {
2315                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2316                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2317                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2318                         }
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2321                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2322                 // ambient model lighting
2323                 mode = SHADERMODE_LIGHTDIRECTION;
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 (r_shadow_bouncegridtexture)
2349                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2350                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2351                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352         }
2353         else
2354         {
2355                 if (r_glsl_offsetmapping.integer)
2356                 {
2357                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2358                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2359                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2360                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2361                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2362                         {
2363                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2364                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2365                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2366                         }
2367                 }
2368                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2369                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2370                 // lightmapped wall
2371                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2372                         permutation |= SHADERPERMUTATION_GLOW;
2373                 if (r_refdef.fogenabled)
2374                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2375                 if (rsurface.texture->colormapping)
2376                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2377                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2378                 {
2379                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2380                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2381
2382                         if (r_shadow_shadowmapsampler)
2383                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2384                         if (r_shadow_shadowmappcf > 1)
2385                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2386                         else if (r_shadow_shadowmappcf)
2387                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2388                 }
2389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2390                         permutation |= SHADERPERMUTATION_REFLECTION;
2391                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2392                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2393                 if (rsurface.texture->reflectmasktexture)
2394                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2395                 if (FAKELIGHT_ENABLED)
2396                 {
2397                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2398                         mode = SHADERMODE_FAKELIGHT;
2399                         permutation |= SHADERPERMUTATION_DIFFUSE;
2400                         if (specularscale > 0)
2401                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402                 }
2403                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2404                 {
2405                         // deluxemapping (light direction texture)
2406                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2407                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2408                         else
2409                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2410                         permutation |= SHADERPERMUTATION_DIFFUSE;
2411                         if (specularscale > 0)
2412                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2413                 }
2414                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2415                 {
2416                         // fake deluxemapping (uniform light direction in tangentspace)
2417                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2418                         permutation |= SHADERPERMUTATION_DIFFUSE;
2419                         if (specularscale > 0)
2420                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2421                 }
2422                 else if (rsurface.uselightmaptexture)
2423                 {
2424                         // ordinary lightmapping (q1bsp, q3bsp)
2425                         mode = SHADERMODE_LIGHTMAP;
2426                 }
2427                 else
2428                 {
2429                         // ordinary vertex coloring (q3bsp)
2430                         mode = SHADERMODE_VERTEXCOLOR;
2431                 }
2432                 if (r_shadow_bouncegridtexture)
2433                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2434                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2436         }
2437         if(!allow_colormod)
2438                 colormod = dummy_colormod;
2439         switch(vid.renderpath)
2440         {
2441         case RENDERPATH_D3D9:
2442 #ifdef SUPPORTD3D
2443                 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);
2444                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2445                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2446                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2447                 if (mode == SHADERMODE_LIGHTSOURCE)
2448                 {
2449                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2450                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2451                 }
2452                 else
2453                 {
2454                         if (mode == SHADERMODE_LIGHTDIRECTION)
2455                         {
2456                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2457                         }
2458                 }
2459                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2460                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2461                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2462                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2463                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2464
2465                 if (mode == SHADERMODE_LIGHTSOURCE)
2466                 {
2467                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2469                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2470                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2471                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2472
2473                         // additive passes are only darkened by fog, not tinted
2474                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2475                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2476                 }
2477                 else
2478                 {
2479                         if (mode == SHADERMODE_FLATCOLOR)
2480                         {
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2482                         }
2483                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2484                         {
2485                                 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]);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2487                                 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);
2488                                 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);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2492                         }
2493                         else
2494                         {
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2496                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2497                                 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);
2498                                 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);
2499                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2500                         }
2501                         // additive passes are only darkened by fog, not tinted
2502                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2503                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2504                         else
2505                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2506                         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);
2507                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2508                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2509                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2510                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2511                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2512                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2513                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2514                         if (mode == SHADERMODE_WATER)
2515                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2516                 }
2517                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2518                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2519                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2520                 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));
2521                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2522                 if (rsurface.texture->pantstexture)
2523                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2524                 else
2525                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2526                 if (rsurface.texture->shirttexture)
2527                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2528                 else
2529                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2530                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2532                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2533                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2534                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2535                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2536                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2537
2538                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2539                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2540                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2541                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2543                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2544                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2545                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2546                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2547                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2548                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2549                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2550                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2551                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2552                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2553                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2554                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2555                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2556                 {
2557                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2558                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2559                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2560                 }
2561                 else
2562                 {
2563                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564                 }
2565 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2566 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2567                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2568                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2569                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2570                 {
2571                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2572                         if (rsurface.rtlight)
2573                         {
2574                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2575                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2576                         }
2577                 }
2578 #endif
2579                 break;
2580         case RENDERPATH_D3D10:
2581                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2582                 break;
2583         case RENDERPATH_D3D11:
2584                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2585                 break;
2586         case RENDERPATH_GL20:
2587         case RENDERPATH_GLES2:
2588                 if (!vid.useinterleavedarrays)
2589                 {
2590                         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);
2591                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2592                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2593                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2594                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2595                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2596                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2597                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2598                 }
2599                 else
2600                 {
2601                         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);
2602                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2603                 }
2604                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2605                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2609                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2611                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2612                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2613                         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);
2614         
2615                         // additive passes are only darkened by fog, not tinted
2616                         if (r_glsl_permutation->loc_FogColor >= 0)
2617                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2618                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2619                 }
2620                 else
2621                 {
2622                         if (mode == SHADERMODE_FLATCOLOR)
2623                         {
2624                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2625                         }
2626                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2627                         {
2628                                 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]);
2629                                 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]);
2630                                 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);
2631                                 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);
2632                                 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);
2633                                 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]);
2634                                 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]);
2635                         }
2636                         else
2637                         {
2638                                 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]);
2639                                 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]);
2640                                 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);
2641                                 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);
2642                                 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);
2643                         }
2644                         // additive passes are only darkened by fog, not tinted
2645                         if (r_glsl_permutation->loc_FogColor >= 0)
2646                         {
2647                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2648                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2649                                 else
2650                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651                         }
2652                         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);
2653                         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]);
2654                         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]);
2655                         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]);
2656                         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]);
2657                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2658                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2659                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2660                         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]);
2661                 }
2662                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2663                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2664                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2665                 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]);
2666                 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]);
2667
2668                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669                 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));
2670                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2672                 {
2673                         if (rsurface.texture->pantstexture)
2674                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2675                         else
2676                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2677                 }
2678                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2679                 {
2680                         if (rsurface.texture->shirttexture)
2681                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2682                         else
2683                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2684                 }
2685                 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]);
2686                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2687                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2688                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2689                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2690                 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]);
2691                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692                 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);}
2693                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2694
2695                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2696                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2697                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2698                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2699                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2700                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2701                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2705                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2706                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2708                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2709                 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);
2710                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2711                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2712                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2715                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716                 {
2717                         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);
2718                         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);
2719                         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);
2720                 }
2721                 else
2722                 {
2723                         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);
2724                 }
2725                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2726                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2727                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2728                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2729                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730                 {
2731                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2732                         if (rsurface.rtlight)
2733                         {
2734                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2735                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2736                         }
2737                 }
2738                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2739                 CHECKGLERROR
2740                 break;
2741         case RENDERPATH_GL13:
2742         case RENDERPATH_GL11:
2743                 break;
2744         case RENDERPATH_SOFT:
2745                 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);
2746                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747                 R_SetupShader_SetPermutationSoft(mode, permutation);
2748                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749                 if (mode == SHADERMODE_LIGHTSOURCE)
2750                 {
2751                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2757         
2758                         // additive passes are only darkened by fog, not tinted
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2761                 }
2762                 else
2763                 {
2764                         if (mode == SHADERMODE_FLATCOLOR)
2765                         {
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2767                         }
2768                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2769                         {
2770                                 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]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772                                 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);
2773                                 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);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                                 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]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2777                         }
2778                         else
2779                         {
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782                                 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);
2783                                 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);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2785                         }
2786                         // additive passes are only darkened by fog, not tinted
2787                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2789                         else
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791                         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);
2792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794                         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]);
2795                         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]);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2800                 }
2801                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805                 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]);
2806
2807                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808                 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));
2809                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2811                 {
2812                         if (rsurface.texture->pantstexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2816                 }
2817                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2818                 {
2819                         if (rsurface.texture->shirttexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2823                 }
2824                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2829                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2830                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2831
2832                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2833                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2834                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2835                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2836                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2837                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2838                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2839                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2840                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2841                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2842                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2843                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2844                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2845                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2846                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2847                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2848                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2849                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2850                 {
2851                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2852                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2853                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2854                 }
2855                 else
2856                 {
2857                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2858                 }
2859 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2860 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2861                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2862                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2863                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2864                 {
2865                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2866                         if (rsurface.rtlight)
2867                         {
2868                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2869                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2870                         }
2871                 }
2872                 break;
2873         }
2874 }
2875
2876 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2877 {
2878         // select a permutation of the lighting shader appropriate to this
2879         // combination of texture, entity, light source, and fogging, only use the
2880         // minimum features necessary to avoid wasting rendering time in the
2881         // fragment shader on features that are not being used
2882         unsigned int permutation = 0;
2883         unsigned int mode = 0;
2884         const float *lightcolorbase = rtlight->currentcolor;
2885         float ambientscale = rtlight->ambientscale;
2886         float diffusescale = rtlight->diffusescale;
2887         float specularscale = rtlight->specularscale;
2888         // this is the location of the light in view space
2889         vec3_t viewlightorigin;
2890         // this transforms from view space (camera) to light space (cubemap)
2891         matrix4x4_t viewtolight;
2892         matrix4x4_t lighttoview;
2893         float viewtolight16f[16];
2894         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2895         // light source
2896         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2897         if (rtlight->currentcubemap != r_texture_whitecube)
2898                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2899         if (diffusescale > 0)
2900                 permutation |= SHADERPERMUTATION_DIFFUSE;
2901         if (specularscale > 0)
2902                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2903         if (r_shadow_usingshadowmap2d)
2904         {
2905                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2906                 if (r_shadow_shadowmapvsdct)
2907                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2908
2909                 if (r_shadow_shadowmapsampler)
2910                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2911                 if (r_shadow_shadowmappcf > 1)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2913                 else if (r_shadow_shadowmappcf)
2914                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2915         }
2916         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2917         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2918         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2919         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2920         switch(vid.renderpath)
2921         {
2922         case RENDERPATH_D3D9:
2923 #ifdef SUPPORTD3D
2924                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2925                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2926                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2927                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2928                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2929                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2930                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2931                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2932                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2933                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2935
2936                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2937                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2938                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2939                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2940                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2941                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2942 #endif
2943                 break;
2944         case RENDERPATH_D3D10:
2945                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2946                 break;
2947         case RENDERPATH_D3D11:
2948                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2949                 break;
2950         case RENDERPATH_GL20:
2951         case RENDERPATH_GLES2:
2952                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2953                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2954                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2955                 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);
2956                 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);
2957                 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);
2958                 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]);
2959                 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]);
2960                 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));
2961                 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]);
2962                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2963
2964                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2965                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2966                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2967                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2968                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2969                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2970                 break;
2971         case RENDERPATH_GL13:
2972         case RENDERPATH_GL11:
2973                 break;
2974         case RENDERPATH_SOFT:
2975                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2976                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2977                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2978                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2979                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2980                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2981                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2982                 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]);
2983                 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));
2984                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2985                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2986
2987                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2988                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2989                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2990                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2991                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2992                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2993                 break;
2994         }
2995 }
2996
2997 #define SKINFRAME_HASH 1024
2998
2999 typedef struct
3000 {
3001         int loadsequence; // incremented each level change
3002         memexpandablearray_t array;
3003         skinframe_t *hash[SKINFRAME_HASH];
3004 }
3005 r_skinframe_t;
3006 r_skinframe_t r_skinframe;
3007
3008 void R_SkinFrame_PrepareForPurge(void)
3009 {
3010         r_skinframe.loadsequence++;
3011         // wrap it without hitting zero
3012         if (r_skinframe.loadsequence >= 200)
3013                 r_skinframe.loadsequence = 1;
3014 }
3015
3016 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3017 {
3018         if (!skinframe)
3019                 return;
3020         // mark the skinframe as used for the purging code
3021         skinframe->loadsequence = r_skinframe.loadsequence;
3022 }
3023
3024 void R_SkinFrame_Purge(void)
3025 {
3026         int i;
3027         skinframe_t *s;
3028         for (i = 0;i < SKINFRAME_HASH;i++)
3029         {
3030                 for (s = r_skinframe.hash[i];s;s = s->next)
3031                 {
3032                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3033                         {
3034                                 if (s->merged == s->base)
3035                                         s->merged = NULL;
3036                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3037                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3038                                 R_PurgeTexture(s->merged);s->merged = NULL;
3039                                 R_PurgeTexture(s->base  );s->base   = NULL;
3040                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3041                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3042                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3043                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3044                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3045                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3046                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3047                                 s->loadsequence = 0;
3048                         }
3049                 }
3050         }
3051 }
3052
3053 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3054         skinframe_t *item;
3055         char basename[MAX_QPATH];
3056
3057         Image_StripImageExtension(name, basename, sizeof(basename));
3058
3059         if( last == NULL ) {
3060                 int hashindex;
3061                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3062                 item = r_skinframe.hash[hashindex];
3063         } else {
3064                 item = last->next;
3065         }
3066
3067         // linearly search through the hash bucket
3068         for( ; item ; item = item->next ) {
3069                 if( !strcmp( item->basename, basename ) ) {
3070                         return item;
3071                 }
3072         }
3073         return NULL;
3074 }
3075
3076 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3077 {
3078         skinframe_t *item;
3079         int hashindex;
3080         char basename[MAX_QPATH];
3081
3082         Image_StripImageExtension(name, basename, sizeof(basename));
3083
3084         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3085         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3086                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3087                         break;
3088
3089         if (!item) {
3090                 rtexture_t *dyntexture;
3091                 // check whether its a dynamic texture
3092                 dyntexture = CL_GetDynTexture( basename );
3093                 if (!add && !dyntexture)
3094                         return NULL;
3095                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3096                 memset(item, 0, sizeof(*item));
3097                 strlcpy(item->basename, basename, sizeof(item->basename));
3098                 item->base = dyntexture; // either NULL or dyntexture handle
3099                 item->textureflags = textureflags;
3100                 item->comparewidth = comparewidth;
3101                 item->compareheight = compareheight;
3102                 item->comparecrc = comparecrc;
3103                 item->next = r_skinframe.hash[hashindex];
3104                 r_skinframe.hash[hashindex] = item;
3105         }
3106         else if( item->base == NULL )
3107         {
3108                 rtexture_t *dyntexture;
3109                 // check whether its a dynamic texture
3110                 // 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]
3111                 dyntexture = CL_GetDynTexture( basename );
3112                 item->base = dyntexture; // either NULL or dyntexture handle
3113         }
3114
3115         R_SkinFrame_MarkUsed(item);
3116         return item;
3117 }
3118
3119 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3120         { \
3121                 unsigned long long avgcolor[5], wsum; \
3122                 int pix, comp, w; \
3123                 avgcolor[0] = 0; \
3124                 avgcolor[1] = 0; \
3125                 avgcolor[2] = 0; \
3126                 avgcolor[3] = 0; \
3127                 avgcolor[4] = 0; \
3128                 wsum = 0; \
3129                 for(pix = 0; pix < cnt; ++pix) \
3130                 { \
3131                         w = 0; \
3132                         for(comp = 0; comp < 3; ++comp) \
3133                                 w += getpixel; \
3134                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3135                         { \
3136                                 ++wsum; \
3137                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3138                                 w = getpixel; \
3139                                 for(comp = 0; comp < 3; ++comp) \
3140                                         avgcolor[comp] += getpixel * w; \
3141                                 avgcolor[3] += w; \
3142                         } \
3143                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                         avgcolor[4] += getpixel; \
3145                 } \
3146                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3147                         avgcolor[3] = 1; \
3148                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3149                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3150                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3151                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3152         }
3153
3154 extern cvar_t gl_picmip;
3155 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3156 {
3157         int j;
3158         unsigned char *pixels;
3159         unsigned char *bumppixels;
3160         unsigned char *basepixels = NULL;
3161         int basepixels_width = 0;
3162         int basepixels_height = 0;
3163         skinframe_t *skinframe;
3164         rtexture_t *ddsbase = NULL;
3165         qboolean ddshasalpha = false;
3166         float ddsavgcolor[4];
3167         char basename[MAX_QPATH];
3168         int miplevel = R_PicmipForFlags(textureflags);
3169         int savemiplevel = miplevel;
3170         int mymiplevel;
3171
3172         if (cls.state == ca_dedicated)
3173                 return NULL;
3174
3175         // return an existing skinframe if already loaded
3176         // if loading of the first image fails, don't make a new skinframe as it
3177         // would cause all future lookups of this to be missing
3178         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3179         if (skinframe && skinframe->base)
3180                 return skinframe;
3181
3182         Image_StripImageExtension(name, basename, sizeof(basename));
3183
3184         // check for DDS texture file first
3185         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3186         {
3187                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3188                 if (basepixels == NULL)
3189                         return NULL;
3190         }
3191
3192         // FIXME handle miplevel
3193
3194         if (developer_loading.integer)
3195                 Con_Printf("loading skin \"%s\"\n", name);
3196
3197         // we've got some pixels to store, so really allocate this new texture now
3198         if (!skinframe)
3199                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3200         skinframe->stain = NULL;
3201         skinframe->merged = NULL;
3202         skinframe->base = NULL;
3203         skinframe->pants = NULL;
3204         skinframe->shirt = NULL;
3205         skinframe->nmap = NULL;
3206         skinframe->gloss = NULL;
3207         skinframe->glow = NULL;
3208         skinframe->fog = NULL;
3209         skinframe->reflect = NULL;
3210         skinframe->hasalpha = false;
3211
3212         if (ddsbase)
3213         {
3214                 skinframe->base = ddsbase;
3215                 skinframe->hasalpha = ddshasalpha;
3216                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3217                 if (r_loadfog && skinframe->hasalpha)
3218                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3219                 //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]);
3220         }
3221         else
3222         {
3223                 basepixels_width = image_width;
3224                 basepixels_height = image_height;
3225                 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);
3226                 if (textureflags & TEXF_ALPHA)
3227                 {
3228                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3229                         {
3230                                 if (basepixels[j] < 255)
3231                                 {
3232                                         skinframe->hasalpha = true;
3233                                         break;
3234                                 }
3235                         }
3236                         if (r_loadfog && skinframe->hasalpha)
3237                         {
3238                                 // has transparent pixels
3239                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3240                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3241                                 {
3242                                         pixels[j+0] = 255;
3243                                         pixels[j+1] = 255;
3244                                         pixels[j+2] = 255;
3245                                         pixels[j+3] = basepixels[j+3];
3246                                 }
3247                                 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);
3248                                 Mem_Free(pixels);
3249                         }
3250                 }
3251                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3252                 //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]);
3253                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3254                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3255                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3256                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3257         }
3258
3259         if (r_loaddds)
3260         {
3261                 mymiplevel = savemiplevel;
3262                 if (r_loadnormalmap)
3263                         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);
3264                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3265                 if (r_loadgloss)
3266                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270         }
3271
3272         // _norm is the name used by tenebrae and has been adopted as standard
3273         if (r_loadnormalmap && skinframe->nmap == NULL)
3274         {
3275                 mymiplevel = savemiplevel;
3276                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3277                 {
3278                         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);
3279                         Mem_Free(pixels);
3280                         pixels = NULL;
3281                 }
3282                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3285                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3286                         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);
3287                         Mem_Free(pixels);
3288                         Mem_Free(bumppixels);
3289                 }
3290                 else if (r_shadow_bumpscale_basetexture.value > 0)
3291                 {
3292                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3293                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3294                         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);
3295                         Mem_Free(pixels);
3296                 }
3297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3298                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3299         }
3300
3301         // _luma is supported only for tenebrae compatibility
3302         // _glow is the preferred name
3303         mymiplevel = savemiplevel;
3304         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))))
3305         {
3306                 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);
3307                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3308                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3309                 Mem_Free(pixels);pixels = NULL;
3310         }
3311
3312         mymiplevel = savemiplevel;
3313         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3314         {
3315                 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);
3316                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3317                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3318                 Mem_Free(pixels);
3319                 pixels = NULL;
3320         }
3321
3322         mymiplevel = savemiplevel;
3323         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3324         {
3325                 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);
3326                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3327                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3328                 Mem_Free(pixels);
3329                 pixels = NULL;
3330         }
3331
3332         mymiplevel = savemiplevel;
3333         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3334         {
3335                 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);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3337                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3338                 Mem_Free(pixels);
3339                 pixels = NULL;
3340         }
3341
3342         mymiplevel = savemiplevel;
3343         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3344         {
3345                 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);
3346                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3347                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3348                 Mem_Free(pixels);
3349                 pixels = NULL;
3350         }
3351
3352         if (basepixels)
3353                 Mem_Free(basepixels);
3354
3355         return skinframe;
3356 }
3357
3358 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3359 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3360 {
3361         int i;
3362         unsigned char *temp1, *temp2;
3363         skinframe_t *skinframe;
3364
3365         if (cls.state == ca_dedicated)
3366                 return NULL;
3367
3368         // if already loaded just return it, otherwise make a new skinframe
3369         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3370         if (skinframe && skinframe->base)
3371                 return skinframe;
3372
3373         skinframe->stain = NULL;
3374         skinframe->merged = NULL;
3375         skinframe->base = NULL;
3376         skinframe->pants = NULL;
3377         skinframe->shirt = NULL;
3378         skinframe->nmap = NULL;
3379         skinframe->gloss = NULL;
3380         skinframe->glow = NULL;
3381         skinframe->fog = NULL;
3382         skinframe->reflect = NULL;
3383         skinframe->hasalpha = false;
3384
3385         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3386         if (!skindata)
3387                 return NULL;
3388
3389         if (developer_loading.integer)
3390                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3391
3392         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3393         {
3394                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3395                 temp2 = temp1 + width * height * 4;
3396                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3397                 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);
3398                 Mem_Free(temp1);
3399         }
3400         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3401         if (textureflags & TEXF_ALPHA)
3402         {
3403                 for (i = 3;i < width * height * 4;i += 4)
3404                 {
3405                         if (skindata[i] < 255)
3406                         {
3407                                 skinframe->hasalpha = true;
3408                                 break;
3409                         }
3410                 }
3411                 if (r_loadfog && skinframe->hasalpha)
3412                 {
3413                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3414                         memcpy(fogpixels, skindata, width * height * 4);
3415                         for (i = 0;i < width * height * 4;i += 4)
3416                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3417                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3418                         Mem_Free(fogpixels);
3419                 }
3420         }
3421
3422         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3423         //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]);
3424
3425         return skinframe;
3426 }
3427
3428 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3429 {
3430         int i;
3431         int featuresmask;
3432         skinframe_t *skinframe;
3433
3434         if (cls.state == ca_dedicated)
3435                 return NULL;
3436
3437         // if already loaded just return it, otherwise make a new skinframe
3438         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3439         if (skinframe && skinframe->base)
3440                 return skinframe;
3441
3442         skinframe->stain = NULL;
3443         skinframe->merged = NULL;
3444         skinframe->base = NULL;
3445         skinframe->pants = NULL;
3446         skinframe->shirt = NULL;
3447         skinframe->nmap = NULL;
3448         skinframe->gloss = NULL;
3449         skinframe->glow = NULL;
3450         skinframe->fog = NULL;
3451         skinframe->reflect = NULL;
3452         skinframe->hasalpha = false;
3453
3454         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3455         if (!skindata)
3456                 return NULL;
3457
3458         if (developer_loading.integer)
3459                 Con_Printf("loading quake skin \"%s\"\n", name);
3460
3461         // 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)
3462         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3463         memcpy(skinframe->qpixels, skindata, width*height);
3464         skinframe->qwidth = width;
3465         skinframe->qheight = height;
3466
3467         featuresmask = 0;
3468         for (i = 0;i < width * height;i++)
3469                 featuresmask |= palette_featureflags[skindata[i]];
3470
3471         skinframe->hasalpha = false;
3472         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3473         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3474         skinframe->qgeneratemerged = true;
3475         skinframe->qgeneratebase = skinframe->qhascolormapping;
3476         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3477
3478         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3479         //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]);
3480
3481         return skinframe;
3482 }
3483
3484 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3485 {
3486         int width;
3487         int height;
3488         unsigned char *skindata;
3489
3490         if (!skinframe->qpixels)
3491                 return;
3492
3493         if (!skinframe->qhascolormapping)
3494                 colormapped = false;
3495
3496         if (colormapped)
3497         {
3498                 if (!skinframe->qgeneratebase)
3499                         return;
3500         }
3501         else
3502         {
3503                 if (!skinframe->qgeneratemerged)
3504                         return;
3505         }
3506
3507         width = skinframe->qwidth;
3508         height = skinframe->qheight;
3509         skindata = skinframe->qpixels;
3510
3511         if (skinframe->qgeneratenmap)
3512         {
3513                 unsigned char *temp1, *temp2;
3514                 skinframe->qgeneratenmap = false;
3515                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3516                 temp2 = temp1 + width * height * 4;
3517                 // use either a custom palette or the quake palette
3518                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3519                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3520                 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);
3521                 Mem_Free(temp1);
3522         }
3523
3524         if (skinframe->qgenerateglow)
3525         {
3526                 skinframe->qgenerateglow = false;
3527                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3528         }
3529
3530         if (colormapped)
3531         {
3532                 skinframe->qgeneratebase = false;
3533                 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);
3534                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3535                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3536         }
3537         else
3538         {
3539                 skinframe->qgeneratemerged = false;
3540                 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);
3541         }
3542
3543         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3544         {
3545                 Mem_Free(skinframe->qpixels);
3546                 skinframe->qpixels = NULL;
3547         }
3548 }
3549
3550 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)
3551 {
3552         int i;
3553         skinframe_t *skinframe;
3554
3555         if (cls.state == ca_dedicated)
3556                 return NULL;
3557
3558         // if already loaded just return it, otherwise make a new skinframe
3559         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3560         if (skinframe && skinframe->base)
3561                 return skinframe;
3562
3563         skinframe->stain = NULL;
3564         skinframe->merged = NULL;
3565         skinframe->base = NULL;
3566         skinframe->pants = NULL;
3567         skinframe->shirt = NULL;
3568         skinframe->nmap = NULL;
3569         skinframe->gloss = NULL;
3570         skinframe->glow = NULL;
3571         skinframe->fog = NULL;
3572         skinframe->reflect = NULL;
3573         skinframe->hasalpha = false;
3574
3575         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3576         if (!skindata)
3577                 return NULL;
3578
3579         if (developer_loading.integer)
3580                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3581
3582         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3583         if (textureflags & TEXF_ALPHA)
3584         {
3585                 for (i = 0;i < width * height;i++)
3586                 {
3587                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3588                         {
3589                                 skinframe->hasalpha = true;
3590                                 break;
3591                         }
3592                 }
3593                 if (r_loadfog && skinframe->hasalpha)
3594                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3595         }
3596
3597         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3598         //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]);
3599
3600         return skinframe;
3601 }
3602
3603 skinframe_t *R_SkinFrame_LoadMissing(void)
3604 {
3605         skinframe_t *skinframe;
3606
3607         if (cls.state == ca_dedicated)
3608                 return NULL;
3609
3610         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3611         skinframe->stain = NULL;
3612         skinframe->merged = NULL;
3613         skinframe->base = NULL;
3614         skinframe->pants = NULL;
3615         skinframe->shirt = NULL;
3616         skinframe->nmap = NULL;
3617         skinframe->gloss = NULL;
3618         skinframe->glow = NULL;
3619         skinframe->fog = NULL;
3620         skinframe->reflect = NULL;
3621         skinframe->hasalpha = false;
3622
3623         skinframe->avgcolor[0] = rand() / RAND_MAX;
3624         skinframe->avgcolor[1] = rand() / RAND_MAX;
3625         skinframe->avgcolor[2] = rand() / RAND_MAX;
3626         skinframe->avgcolor[3] = 1;
3627
3628         return skinframe;
3629 }
3630
3631 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3632 typedef struct suffixinfo_s
3633 {
3634         const char *suffix;
3635         qboolean flipx, flipy, flipdiagonal;
3636 }
3637 suffixinfo_t;
3638 static suffixinfo_t suffix[3][6] =
3639 {
3640         {
3641                 {"px",   false, false, false},
3642                 {"nx",   false, false, false},
3643                 {"py",   false, false, false},
3644                 {"ny",   false, false, false},
3645                 {"pz",   false, false, false},
3646                 {"nz",   false, false, false}
3647         },
3648         {
3649                 {"posx", false, false, false},
3650                 {"negx", false, false, false},
3651                 {"posy", false, false, false},
3652                 {"negy", false, false, false},
3653                 {"posz", false, false, false},
3654                 {"negz", false, false, false}
3655         },
3656         {
3657                 {"rt",    true, false,  true},
3658                 {"lf",   false,  true,  true},
3659                 {"ft",    true,  true, false},
3660                 {"bk",   false, false, false},
3661                 {"up",    true, false,  true},
3662                 {"dn",    true, false,  true}
3663         }
3664 };
3665
3666 static int componentorder[4] = {0, 1, 2, 3};
3667
3668 rtexture_t *R_LoadCubemap(const char *basename)
3669 {
3670         int i, j, cubemapsize;
3671         unsigned char *cubemappixels, *image_buffer;
3672         rtexture_t *cubemaptexture;
3673         char name[256];
3674         // must start 0 so the first loadimagepixels has no requested width/height
3675         cubemapsize = 0;
3676         cubemappixels = NULL;
3677         cubemaptexture = NULL;
3678         // keep trying different suffix groups (posx, px, rt) until one loads
3679         for (j = 0;j < 3 && !cubemappixels;j++)
3680         {
3681                 // load the 6 images in the suffix group
3682                 for (i = 0;i < 6;i++)
3683                 {
3684                         // generate an image name based on the base and and suffix
3685                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3686                         // load it
3687                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3688                         {
3689                                 // an image loaded, make sure width and height are equal
3690                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3691                                 {
3692                                         // if this is the first image to load successfully, allocate the cubemap memory
3693                                         if (!cubemappixels && image_width >= 1)
3694                                         {
3695                                                 cubemapsize = image_width;
3696                                                 // note this clears to black, so unavailable sides are black
3697                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3698                                         }
3699                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3700                                         if (cubemappixels)
3701                                                 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);
3702                                 }
3703                                 else
3704                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3705                                 // free the image
3706                                 Mem_Free(image_buffer);
3707                         }
3708                 }
3709         }
3710         // if a cubemap loaded, upload it
3711         if (cubemappixels)
3712         {
3713                 if (developer_loading.integer)
3714                         Con_Printf("loading cubemap \"%s\"\n", basename);
3715
3716                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3717                 Mem_Free(cubemappixels);
3718         }
3719         else
3720         {
3721                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3722                 if (developer_loading.integer)
3723                 {
3724                         Con_Printf("(tried tried images ");
3725                         for (j = 0;j < 3;j++)
3726                                 for (i = 0;i < 6;i++)
3727                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3728                         Con_Print(" and was unable to find any of them).\n");
3729                 }
3730         }
3731         return cubemaptexture;
3732 }
3733
3734 rtexture_t *R_GetCubemap(const char *basename)
3735 {
3736         int i;
3737         for (i = 0;i < r_texture_numcubemaps;i++)
3738                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3739                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3740         if (i >= MAX_CUBEMAPS)
3741                 return r_texture_whitecube;
3742         r_texture_numcubemaps++;
3743         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3744         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3745         return r_texture_cubemaps[i].texture;
3746 }
3747
3748 void R_FreeCubemaps(void)
3749 {
3750         int i;
3751         for (i = 0;i < r_texture_numcubemaps;i++)
3752         {
3753                 if (developer_loading.integer)
3754                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3755                 if (r_texture_cubemaps[i].texture)
3756                         R_FreeTexture(r_texture_cubemaps[i].texture);
3757         }
3758         r_texture_numcubemaps = 0;
3759 }
3760
3761 void R_Main_FreeViewCache(void)
3762 {
3763         if (r_refdef.viewcache.entityvisible)
3764                 Mem_Free(r_refdef.viewcache.entityvisible);
3765         if (r_refdef.viewcache.world_pvsbits)
3766                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3767         if (r_refdef.viewcache.world_leafvisible)
3768                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3769         if (r_refdef.viewcache.world_surfacevisible)
3770                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3771         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3772 }
3773
3774 void R_Main_ResizeViewCache(void)
3775 {
3776         int numentities = r_refdef.scene.numentities;
3777         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3778         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3779         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3780         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3781         if (r_refdef.viewcache.maxentities < numentities)
3782         {
3783                 r_refdef.viewcache.maxentities = numentities;
3784                 if (r_refdef.viewcache.entityvisible)
3785                         Mem_Free(r_refdef.viewcache.entityvisible);
3786                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3787         }
3788         if (r_refdef.viewcache.world_numclusters != numclusters)
3789         {
3790                 r_refdef.viewcache.world_numclusters = numclusters;
3791                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3792                 if (r_refdef.viewcache.world_pvsbits)
3793                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3794                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3795         }
3796         if (r_refdef.viewcache.world_numleafs != numleafs)
3797         {
3798                 r_refdef.viewcache.world_numleafs = numleafs;
3799                 if (r_refdef.viewcache.world_leafvisible)
3800                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3801                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3802         }
3803         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3804         {
3805                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3806                 if (r_refdef.viewcache.world_surfacevisible)
3807                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3808                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3809         }
3810 }
3811
3812 extern rtexture_t *loadingscreentexture;
3813 void gl_main_start(void)
3814 {
3815         loadingscreentexture = NULL;
3816         r_texture_blanknormalmap = NULL;
3817         r_texture_white = NULL;
3818         r_texture_grey128 = NULL;
3819         r_texture_black = NULL;
3820         r_texture_whitecube = NULL;
3821         r_texture_normalizationcube = NULL;
3822         r_texture_fogattenuation = NULL;
3823         r_texture_fogheighttexture = NULL;
3824         r_texture_gammaramps = NULL;
3825         r_texture_numcubemaps = 0;
3826
3827         r_loaddds = r_texture_dds_load.integer != 0;
3828         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3829
3830         switch(vid.renderpath)
3831         {
3832         case RENDERPATH_GL20:
3833         case RENDERPATH_D3D9:
3834         case RENDERPATH_D3D10:
3835         case RENDERPATH_D3D11:
3836         case RENDERPATH_SOFT:
3837                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3838                 Cvar_SetValueQuick(&gl_combine, 1);
3839                 Cvar_SetValueQuick(&r_glsl, 1);
3840                 r_loadnormalmap = true;
3841                 r_loadgloss = true;
3842                 r_loadfog = false;
3843                 break;
3844         case RENDERPATH_GL13:
3845                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3846                 Cvar_SetValueQuick(&gl_combine, 1);
3847                 Cvar_SetValueQuick(&r_glsl, 0);
3848                 r_loadnormalmap = false;
3849                 r_loadgloss = false;
3850                 r_loadfog = true;
3851                 break;
3852         case RENDERPATH_GL11:
3853                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854                 Cvar_SetValueQuick(&gl_combine, 0);
3855                 Cvar_SetValueQuick(&r_glsl, 0);
3856                 r_loadnormalmap = false;
3857                 r_loadgloss = false;
3858                 r_loadfog = true;
3859                 break;
3860         case RENDERPATH_GLES2:
3861                 Cvar_SetValueQuick(&r_textureunits, 1);
3862                 Cvar_SetValueQuick(&gl_combine, 1);
3863                 Cvar_SetValueQuick(&r_glsl, 1);
3864                 r_loadnormalmap = true;
3865                 r_loadgloss = false;
3866                 r_loadfog = false;
3867                 break;
3868         }
3869
3870         R_AnimCache_Free();
3871         R_FrameData_Reset();
3872
3873         r_numqueries = 0;
3874         r_maxqueries = 0;
3875         memset(r_queries, 0, sizeof(r_queries));
3876
3877         r_qwskincache = NULL;
3878         r_qwskincache_size = 0;
3879
3880         // set up r_skinframe loading system for textures
3881         memset(&r_skinframe, 0, sizeof(r_skinframe));
3882         r_skinframe.loadsequence = 1;
3883         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3884
3885         r_main_texturepool = R_AllocTexturePool();
3886         R_BuildBlankTextures();
3887         R_BuildNoTexture();
3888         if (vid.support.arb_texture_cube_map)
3889         {
3890                 R_BuildWhiteCube();
3891                 R_BuildNormalizationCube();
3892         }
3893         r_texture_fogattenuation = NULL;
3894         r_texture_fogheighttexture = NULL;
3895         r_texture_gammaramps = NULL;
3896         //r_texture_fogintensity = NULL;
3897         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3898         memset(&r_waterstate, 0, sizeof(r_waterstate));
3899         r_glsl_permutation = NULL;
3900         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3901         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3902         glslshaderstring = NULL;
3903 #ifdef SUPPORTD3D
3904         r_hlsl_permutation = NULL;
3905         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3906         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3907 #endif
3908         hlslshaderstring = NULL;
3909         memset(&r_svbsp, 0, sizeof (r_svbsp));
3910
3911         r_refdef.fogmasktable_density = 0;
3912 }
3913
3914 void gl_main_shutdown(void)
3915 {
3916         R_AnimCache_Free();
3917         R_FrameData_Reset();
3918
3919         R_Main_FreeViewCache();
3920
3921         switch(vid.renderpath)
3922         {
3923         case RENDERPATH_GL11:
3924         case RENDERPATH_GL13:
3925         case RENDERPATH_GL20:
3926         case RENDERPATH_GLES2:
3927                 if (r_maxqueries)
3928                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3929                 break;
3930         case RENDERPATH_D3D9:
3931                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3932                 break;
3933         case RENDERPATH_D3D10:
3934                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3935                 break;
3936         case RENDERPATH_D3D11:
3937                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3938                 break;
3939         case RENDERPATH_SOFT:
3940                 break;
3941         }
3942
3943         r_numqueries = 0;
3944         r_maxqueries = 0;
3945         memset(r_queries, 0, sizeof(r_queries));
3946
3947         r_qwskincache = NULL;
3948         r_qwskincache_size = 0;
3949
3950         // clear out the r_skinframe state
3951         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3952         memset(&r_skinframe, 0, sizeof(r_skinframe));
3953
3954         if (r_svbsp.nodes)
3955                 Mem_Free(r_svbsp.nodes);
3956         memset(&r_svbsp, 0, sizeof (r_svbsp));
3957         R_FreeTexturePool(&r_main_texturepool);
3958         loadingscreentexture = NULL;
3959         r_texture_blanknormalmap = NULL;
3960         r_texture_white = NULL;
3961         r_texture_grey128 = NULL;
3962         r_texture_black = NULL;
3963         r_texture_whitecube = NULL;
3964         r_texture_normalizationcube = NULL;
3965         r_texture_fogattenuation = NULL;
3966         r_texture_fogheighttexture = NULL;
3967         r_texture_gammaramps = NULL;
3968         r_texture_numcubemaps = 0;
3969         //r_texture_fogintensity = NULL;
3970         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3971         memset(&r_waterstate, 0, sizeof(r_waterstate));
3972         R_GLSL_Restart_f();
3973
3974         r_glsl_permutation = NULL;
3975         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3976         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3977         glslshaderstring = NULL;
3978 #ifdef SUPPORTD3D
3979         r_hlsl_permutation = NULL;
3980         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3981         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3982 #endif
3983         hlslshaderstring = NULL;
3984 }
3985
3986 extern void CL_ParseEntityLump(char *entitystring);
3987 void gl_main_newmap(void)
3988 {
3989         // FIXME: move this code to client
3990         char *entities, entname[MAX_QPATH];
3991         if (r_qwskincache)
3992                 Mem_Free(r_qwskincache);
3993         r_qwskincache = NULL;
3994         r_qwskincache_size = 0;
3995         if (cl.worldmodel)
3996         {
3997                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3998                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3999                 {
4000                         CL_ParseEntityLump(entities);
4001                         Mem_Free(entities);
4002                         return;
4003                 }
4004                 if (cl.worldmodel->brush.entities)
4005                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4006         }
4007         R_Main_FreeViewCache();
4008
4009         R_FrameData_Reset();
4010 }
4011
4012 void GL_Main_Init(void)
4013 {
4014         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4015
4016         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4017         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4018         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4019         if (gamemode == GAME_NEHAHRA)
4020         {
4021                 Cvar_RegisterVariable (&gl_fogenable);
4022                 Cvar_RegisterVariable (&gl_fogdensity);
4023                 Cvar_RegisterVariable (&gl_fogred);
4024                 Cvar_RegisterVariable (&gl_foggreen);
4025                 Cvar_RegisterVariable (&gl_fogblue);
4026                 Cvar_RegisterVariable (&gl_fogstart);
4027                 Cvar_RegisterVariable (&gl_fogend);
4028                 Cvar_RegisterVariable (&gl_skyclip);
4029         }
4030         Cvar_RegisterVariable(&r_motionblur);
4031         Cvar_RegisterVariable(&r_motionblur_maxblur);
4032         Cvar_RegisterVariable(&r_motionblur_bmin);
4033         Cvar_RegisterVariable(&r_motionblur_vmin);
4034         Cvar_RegisterVariable(&r_motionblur_vmax);
4035         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4036         Cvar_RegisterVariable(&r_motionblur_randomize);
4037         Cvar_RegisterVariable(&r_damageblur);
4038         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4039         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4040         Cvar_RegisterVariable(&r_equalize_entities_by);
4041         Cvar_RegisterVariable(&r_equalize_entities_to);
4042         Cvar_RegisterVariable(&r_depthfirst);
4043         Cvar_RegisterVariable(&r_useinfinitefarclip);
4044         Cvar_RegisterVariable(&r_farclip_base);
4045         Cvar_RegisterVariable(&r_farclip_world);
4046         Cvar_RegisterVariable(&r_nearclip);
4047         Cvar_RegisterVariable(&r_showbboxes);
4048         Cvar_RegisterVariable(&r_showsurfaces);
4049         Cvar_RegisterVariable(&r_showtris);
4050         Cvar_RegisterVariable(&r_shownormals);
4051         Cvar_RegisterVariable(&r_showlighting);
4052         Cvar_RegisterVariable(&r_showshadowvolumes);
4053         Cvar_RegisterVariable(&r_showcollisionbrushes);
4054         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4055         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4056         Cvar_RegisterVariable(&r_showdisabledepthtest);
4057         Cvar_RegisterVariable(&r_drawportals);
4058         Cvar_RegisterVariable(&r_drawentities);
4059         Cvar_RegisterVariable(&r_draw2d);
4060         Cvar_RegisterVariable(&r_drawworld);
4061         Cvar_RegisterVariable(&r_cullentities_trace);
4062         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4063         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4064         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4065         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4066         Cvar_RegisterVariable(&r_drawviewmodel);
4067         Cvar_RegisterVariable(&r_drawexteriormodel);
4068         Cvar_RegisterVariable(&r_speeds);
4069         Cvar_RegisterVariable(&r_fullbrights);
4070         Cvar_RegisterVariable(&r_wateralpha);
4071         Cvar_RegisterVariable(&r_dynamic);
4072         Cvar_RegisterVariable(&r_fakelight);
4073         Cvar_RegisterVariable(&r_fakelight_intensity);
4074         Cvar_RegisterVariable(&r_fullbright);
4075         Cvar_RegisterVariable(&r_shadows);
4076         Cvar_RegisterVariable(&r_shadows_darken);
4077         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4078         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4079         Cvar_RegisterVariable(&r_shadows_throwdistance);
4080         Cvar_RegisterVariable(&r_shadows_throwdirection);
4081         Cvar_RegisterVariable(&r_shadows_focus);
4082         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4083         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4084         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4085         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4086         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4087         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4088         Cvar_RegisterVariable(&r_fog_exp2);
4089         Cvar_RegisterVariable(&r_drawfog);
4090         Cvar_RegisterVariable(&r_transparentdepthmasking);
4091         Cvar_RegisterVariable(&r_texture_dds_load);
4092         Cvar_RegisterVariable(&r_texture_dds_save);
4093         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4094         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4095         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4096         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4097         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4098         Cvar_RegisterVariable(&r_textureunits);
4099         Cvar_RegisterVariable(&gl_combine);
4100         Cvar_RegisterVariable(&r_glsl);
4101         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4102         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4103         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4104         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4105         Cvar_RegisterVariable(&r_glsl_postprocess);
4106         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4107         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4108         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4109         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4110         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4111         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4112         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4113         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4114
4115         Cvar_RegisterVariable(&r_water);
4116         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4117         Cvar_RegisterVariable(&r_water_clippingplanebias);
4118         Cvar_RegisterVariable(&r_water_refractdistort);
4119         Cvar_RegisterVariable(&r_water_reflectdistort);
4120         Cvar_RegisterVariable(&r_water_scissormode);
4121         Cvar_RegisterVariable(&r_lerpsprites);
4122         Cvar_RegisterVariable(&r_lerpmodels);
4123         Cvar_RegisterVariable(&r_lerplightstyles);
4124         Cvar_RegisterVariable(&r_waterscroll);
4125         Cvar_RegisterVariable(&r_bloom);
4126         Cvar_RegisterVariable(&r_bloom_colorscale);
4127         Cvar_RegisterVariable(&r_bloom_brighten);
4128         Cvar_RegisterVariable(&r_bloom_blur);
4129         Cvar_RegisterVariable(&r_bloom_resolution);
4130         Cvar_RegisterVariable(&r_bloom_colorexponent);
4131         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4132         Cvar_RegisterVariable(&r_hdr);
4133         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4134         Cvar_RegisterVariable(&r_hdr_glowintensity);
4135         Cvar_RegisterVariable(&r_hdr_range);
4136         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4137         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4138         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4139         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4140         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4141         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4142         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4143         Cvar_RegisterVariable(&developer_texturelogging);
4144         Cvar_RegisterVariable(&gl_lightmaps);
4145         Cvar_RegisterVariable(&r_test);
4146         Cvar_RegisterVariable(&r_glsl_saturation);
4147         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4148         Cvar_RegisterVariable(&r_framedatasize);
4149         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4150                 Cvar_SetValue("r_fullbrights", 0);
4151         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4152
4153         Cvar_RegisterVariable(&r_track_sprites);
4154         Cvar_RegisterVariable(&r_track_sprites_flags);
4155         Cvar_RegisterVariable(&r_track_sprites_scalew);
4156         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4157         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4158         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4159         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4160         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4161 }
4162
4163 extern void R_Textures_Init(void);
4164 extern void GL_Draw_Init(void);
4165 extern void GL_Main_Init(void);
4166 extern void R_Shadow_Init(void);
4167 extern void R_Sky_Init(void);
4168 extern void GL_Surf_Init(void);
4169 extern void R_Particles_Init(void);
4170 extern void R_Explosion_Init(void);
4171 extern void gl_backend_init(void);
4172 extern void Sbar_Init(void);
4173 extern void R_LightningBeams_Init(void);
4174 extern void Mod_RenderInit(void);
4175 extern void Font_Init(void);
4176
4177 void Render_Init(void)
4178 {
4179         gl_backend_init();
4180         R_Textures_Init();
4181         GL_Main_Init();
4182         Font_Init();
4183         GL_Draw_Init();
4184         R_Shadow_Init();
4185         R_Sky_Init();
4186         GL_Surf_Init();
4187         Sbar_Init();
4188         R_Particles_Init();
4189         R_Explosion_Init();
4190         R_LightningBeams_Init();
4191         Mod_RenderInit();
4192 }
4193
4194 /*
4195 ===============
4196 GL_Init
4197 ===============
4198 */
4199 extern char *ENGINE_EXTENSIONS;
4200 void GL_Init (void)
4201 {
4202         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4203         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4204         gl_version = (const char *)qglGetString(GL_VERSION);
4205         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4206
4207         if (!gl_extensions)
4208                 gl_extensions = "";
4209         if (!gl_platformextensions)
4210                 gl_platformextensions = "";
4211
4212         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4213         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4214         Con_Printf("GL_VERSION: %s\n", gl_version);
4215         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4216         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4217
4218         VID_CheckExtensions();
4219
4220         // LordHavoc: report supported extensions
4221         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4222
4223         // clear to black (loading plaque will be seen over this)
4224         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4225 }
4226
4227 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4228 {
4229         int i;
4230         mplane_t *p;
4231         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4232         {
4233                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4234                 if (i == 4)
4235                         continue;
4236                 p = r_refdef.view.frustum + i;
4237                 switch(p->signbits)
4238                 {
4239                 default:
4240                 case 0:
4241                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4242                                 return true;
4243                         break;
4244                 case 1:
4245                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4246                                 return true;
4247                         break;
4248                 case 2:
4249                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4250                                 return true;
4251                         break;
4252                 case 3:
4253                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4254                                 return true;
4255                         break;
4256                 case 4:
4257                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 5:
4261                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 6:
4265                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 case 7:
4269                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4270                                 return true;
4271                         break;
4272                 }
4273         }
4274         return false;
4275 }
4276
4277 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4278 {
4279         int i;
4280         const mplane_t *p;
4281         for (i = 0;i < numplanes;i++)
4282         {
4283                 p = planes + i;
4284                 switch(p->signbits)
4285                 {
4286                 default:
4287                 case 0:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 1:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 2:
4296                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 3:
4300                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 case 4:
4304                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4305                                 return true;
4306                         break;
4307                 case 5:
4308                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4309                                 return true;
4310                         break;
4311                 case 6:
4312                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4313                                 return true;
4314                         break;
4315                 case 7:
4316                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4317                                 return true;
4318                         break;
4319                 }
4320         }
4321         return false;
4322 }
4323
4324 //==================================================================================
4325
4326 // LordHavoc: this stores temporary data used within the same frame
4327
4328 typedef struct r_framedata_mem_s
4329 {
4330         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4331         size_t size; // how much usable space
4332         size_t current; // how much space in use
4333         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4334         size_t wantedsize; // how much space was allocated
4335         unsigned char *data; // start of real data (16byte aligned)
4336 }
4337 r_framedata_mem_t;
4338
4339 static r_framedata_mem_t *r_framedata_mem;
4340
4341 void R_FrameData_Reset(void)
4342 {
4343         while (r_framedata_mem)
4344         {
4345                 r_framedata_mem_t *next = r_framedata_mem->purge;
4346                 Mem_Free(r_framedata_mem);
4347                 r_framedata_mem = next;
4348         }
4349 }
4350
4351 void R_FrameData_Resize(void)
4352 {
4353         size_t wantedsize;
4354         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4355         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4356         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4357         {
4358                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4359                 newmem->wantedsize = wantedsize;
4360                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4361                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4362                 newmem->current = 0;
4363                 newmem->mark = 0;
4364                 newmem->purge = r_framedata_mem;
4365                 r_framedata_mem = newmem;
4366         }
4367 }
4368
4369 void R_FrameData_NewFrame(void)
4370 {
4371         R_FrameData_Resize();
4372         if (!r_framedata_mem)
4373                 return;
4374         // if we ran out of space on the last frame, free the old memory now
4375         while (r_framedata_mem->purge)
4376         {
4377                 // repeatedly remove the second item in the list, leaving only head
4378                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4379                 Mem_Free(r_framedata_mem->purge);
4380                 r_framedata_mem->purge = next;
4381         }
4382         // reset the current mem pointer
4383         r_framedata_mem->current = 0;
4384         r_framedata_mem->mark = 0;
4385 }
4386
4387 void *R_FrameData_Alloc(size_t size)
4388 {
4389         void *data;
4390
4391         // align to 16 byte boundary - the data pointer is already aligned, so we
4392         // only need to ensure the size of every allocation is also aligned
4393         size = (size + 15) & ~15;
4394
4395         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4396         {
4397                 // emergency - we ran out of space, allocate more memory
4398                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4399                 R_FrameData_Resize();
4400         }
4401
4402         data = r_framedata_mem->data + r_framedata_mem->current;
4403         r_framedata_mem->current += size;
4404
4405         // count the usage for stats
4406         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4407         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4408
4409         return (void *)data;
4410 }
4411
4412 void *R_FrameData_Store(size_t size, void *data)
4413 {
4414         void *d = R_FrameData_Alloc(size);
4415         if (d && data)
4416                 memcpy(d, data, size);
4417         return d;
4418 }
4419
4420 void R_FrameData_SetMark(void)
4421 {
4422         if (!r_framedata_mem)
4423                 return;
4424         r_framedata_mem->mark = r_framedata_mem->current;
4425 }
4426
4427 void R_FrameData_ReturnToMark(void)
4428 {
4429         if (!r_framedata_mem)
4430                 return;
4431         r_framedata_mem->current = r_framedata_mem->mark;
4432 }
4433
4434 //==================================================================================
4435
4436 // LordHavoc: animcache originally written by Echon, rewritten since then
4437
4438 /**
4439  * Animation cache prevents re-generating mesh data for an animated model
4440  * multiple times in one frame for lighting, shadowing, reflections, etc.
4441  */
4442
4443 void R_AnimCache_Free(void)
4444 {
4445 }
4446
4447 void R_AnimCache_ClearCache(void)
4448 {
4449         int i;
4450         entity_render_t *ent;
4451
4452         for (i = 0;i < r_refdef.scene.numentities;i++)
4453         {
4454                 ent = r_refdef.scene.entities[i];
4455                 ent->animcache_vertex3f = NULL;
4456                 ent->animcache_normal3f = NULL;
4457                 ent->animcache_svector3f = NULL;
4458                 ent->animcache_tvector3f = NULL;
4459                 ent->animcache_vertexmesh = NULL;
4460                 ent->animcache_vertex3fbuffer = NULL;
4461                 ent->animcache_vertexmeshbuffer = NULL;
4462         }
4463 }
4464
4465 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4466 {
4467         int i;
4468
4469         // check if we need the meshbuffers
4470         if (!vid.useinterleavedarrays)
4471                 return;
4472
4473         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4474                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4475         // TODO: upload vertex3f buffer?
4476         if (ent->animcache_vertexmesh)
4477         {
4478                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4479                 for (i = 0;i < numvertices;i++)
4480                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4481                 if (ent->animcache_svector3f)
4482                         for (i = 0;i < numvertices;i++)
4483                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4484                 if (ent->animcache_tvector3f)
4485                         for (i = 0;i < numvertices;i++)
4486                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4487                 if (ent->animcache_normal3f)
4488                         for (i = 0;i < numvertices;i++)
4489                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4490                 // TODO: upload vertexmeshbuffer?
4491         }
4492 }
4493
4494 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4495 {
4496         dp_model_t *model = ent->model;
4497         int numvertices;
4498         // see if it's already cached this frame
4499         if (ent->animcache_vertex3f)
4500         {
4501                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4502                 if (wantnormals || wanttangents)
4503                 {
4504                         if (ent->animcache_normal3f)
4505                                 wantnormals = false;
4506                         if (ent->animcache_svector3f)
4507                                 wanttangents = false;
4508                         if (wantnormals || wanttangents)
4509                         {
4510                                 numvertices = model->surfmesh.num_vertices;
4511                                 if (wantnormals)
4512                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4513                                 if (wanttangents)
4514                                 {
4515                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4516                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4517                                 }
4518                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4519                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4520                         }
4521                 }
4522         }
4523         else
4524         {
4525                 // see if this ent is worth caching
4526                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4527                         return false;
4528                 // get some memory for this entity and generate mesh data
4529                 numvertices = model->surfmesh.num_vertices;
4530                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531                 if (wantnormals)
4532                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533                 if (wanttangents)
4534                 {
4535                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4537                 }
4538                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4539                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4540         }
4541         return true;
4542 }
4543
4544 void R_AnimCache_CacheVisibleEntities(void)
4545 {
4546         int i;
4547         qboolean wantnormals = true;
4548         qboolean wanttangents = !r_showsurfaces.integer;
4549
4550         switch(vid.renderpath)
4551         {
4552         case RENDERPATH_GL20:
4553         case RENDERPATH_D3D9:
4554         case RENDERPATH_D3D10:
4555         case RENDERPATH_D3D11:
4556         case RENDERPATH_GLES2:
4557                 break;
4558         case RENDERPATH_GL13:
4559         case RENDERPATH_GL11:
4560                 wanttangents = false;
4561                 break;
4562         case RENDERPATH_SOFT:
4563                 break;
4564         }
4565
4566         if (r_shownormals.integer)
4567                 wanttangents = wantnormals = true;
4568
4569         // TODO: thread this
4570         // NOTE: R_PrepareRTLights() also caches entities
4571
4572         for (i = 0;i < r_refdef.scene.numentities;i++)
4573                 if (r_refdef.viewcache.entityvisible[i])
4574                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4575 }
4576
4577 //==================================================================================
4578
4579 static void R_View_UpdateEntityLighting (void)
4580 {
4581         int i;
4582         entity_render_t *ent;
4583         vec3_t tempdiffusenormal, avg;
4584         vec_t f, fa, fd, fdd;
4585         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4586
4587         for (i = 0;i < r_refdef.scene.numentities;i++)
4588         {
4589                 ent = r_refdef.scene.entities[i];
4590
4591                 // skip unseen models
4592                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4593                         continue;
4594
4595                 // skip bsp models
4596                 if (ent->model && ent->model->brush.num_leafs)
4597                 {
4598                         // TODO: use modellight for r_ambient settings on world?
4599                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4600                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4601                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4602                         continue;
4603                 }
4604
4605                 // fetch the lighting from the worldmodel data
4606                 VectorClear(ent->modellight_ambient);
4607                 VectorClear(ent->modellight_diffuse);
4608                 VectorClear(tempdiffusenormal);
4609                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4610                 {
4611                         vec3_t org;
4612                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4613
4614                         // complete lightning for lit sprites
4615                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4616                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4617                         {
4618                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4619                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4620                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4621                         }
4622                         else
4623                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4624
4625                         if(ent->flags & RENDER_EQUALIZE)
4626                         {
4627                                 // first fix up ambient lighting...
4628                                 if(r_equalize_entities_minambient.value > 0)
4629                                 {
4630                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4631                                         if(fd > 0)
4632                                         {
4633                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4634                                                 if(fa < r_equalize_entities_minambient.value * fd)
4635                                                 {
4636                                                         // solve:
4637                                                         //   fa'/fd' = minambient
4638                                                         //   fa'+0.25*fd' = fa+0.25*fd
4639                                                         //   ...
4640                                                         //   fa' = fd' * minambient
4641                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4642                                                         //   ...
4643                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4644                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4645                                                         //   ...
4646                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4647                                                         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
4648                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4649                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4650                                                 }
4651                                         }
4652                                 }
4653
4654                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4655                                 {
4656                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4657                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4658                                         f = fa + 0.25 * fd;
4659                                         if(f > 0)
4660                                         {
4661                                                 // adjust brightness and saturation to target
4662                                                 avg[0] = avg[1] = avg[2] = fa / f;
4663                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4664                                                 avg[0] = avg[1] = avg[2] = fd / f;
4665                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4666                                         }
4667                                 }
4668                         }
4669                 }
4670                 else // highly rare
4671                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4672
4673                 // move the light direction into modelspace coordinates for lighting code
4674                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4675                 if(VectorLength2(ent->modellight_lightdir) == 0)
4676                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4677                 VectorNormalize(ent->modellight_lightdir);
4678         }
4679 }
4680
4681 #define MAX_LINEOFSIGHTTRACES 64
4682
4683 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4684 {
4685         int i;
4686         vec3_t boxmins, boxmaxs;
4687         vec3_t start;
4688         vec3_t end;
4689         dp_model_t *model = r_refdef.scene.worldmodel;
4690
4691         if (!model || !model->brush.TraceLineOfSight)
4692                 return true;
4693
4694         // expand the box a little
4695         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4696         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4697         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4698         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4699         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4700         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4701
4702         // return true if eye is inside enlarged box
4703         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4704                 return true;
4705
4706         // try center
4707         VectorCopy(eye, start);
4708         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4709         if (model->brush.TraceLineOfSight(model, start, end))
4710                 return true;
4711
4712         // try various random positions
4713         for (i = 0;i < numsamples;i++)
4714         {
4715                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4716                 if (model->brush.TraceLineOfSight(model, start, end))
4717                         return true;
4718         }
4719
4720         return false;
4721 }
4722
4723
4724 static void R_View_UpdateEntityVisible (void)
4725 {
4726         int i;
4727         int renderimask;
4728         int samples;
4729         entity_render_t *ent;
4730
4731         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4732                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4733                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4734                 :                                                          RENDER_EXTERIORMODEL;
4735         if (!r_drawviewmodel.integer)
4736                 renderimask |= RENDER_VIEWMODEL;
4737         if (!r_drawexteriormodel.integer)
4738                 renderimask |= RENDER_EXTERIORMODEL;
4739         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4740         {
4741                 // worldmodel can check visibility
4742                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4743                 for (i = 0;i < r_refdef.scene.numentities;i++)
4744                 {
4745                         ent = r_refdef.scene.entities[i];
4746                         if (!(ent->flags & renderimask))
4747                         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)))
4748                         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))
4749                                 r_refdef.viewcache.entityvisible[i] = true;
4750                 }
4751                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4752                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4753                 {
4754                         for (i = 0;i < r_refdef.scene.numentities;i++)
4755                         {
4756                                 ent = r_refdef.scene.entities[i];
4757                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4758                                 {
4759                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4760                                         if (samples < 0)
4761                                                 continue; // temp entities do pvs only
4762                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4763                                                 ent->last_trace_visibility = realtime;
4764                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4765                                                 r_refdef.viewcache.entityvisible[i] = 0;
4766                                 }
4767                         }
4768                 }
4769         }
4770         else
4771         {
4772                 // no worldmodel or it can't check visibility
4773                 for (i = 0;i < r_refdef.scene.numentities;i++)
4774                 {
4775                         ent = r_refdef.scene.entities[i];
4776                         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));
4777                 }
4778         }
4779 }
4780
4781 /// only used if skyrendermasked, and normally returns false
4782 int R_DrawBrushModelsSky (void)
4783 {
4784         int i, sky;
4785         entity_render_t *ent;
4786
4787         sky = false;
4788         for (i = 0;i < r_refdef.scene.numentities;i++)
4789         {
4790                 if (!r_refdef.viewcache.entityvisible[i])
4791                         continue;
4792                 ent = r_refdef.scene.entities[i];
4793                 if (!ent->model || !ent->model->DrawSky)
4794                         continue;
4795                 ent->model->DrawSky(ent);
4796                 sky = true;
4797         }
4798         return sky;
4799 }
4800
4801 static void R_DrawNoModel(entity_render_t *ent);
4802 static void R_DrawModels(void)
4803 {
4804         int i;
4805         entity_render_t *ent;
4806
4807         for (i = 0;i < r_refdef.scene.numentities;i++)
4808         {
4809                 if (!r_refdef.viewcache.entityvisible[i])
4810                         continue;
4811                 ent = r_refdef.scene.entities[i];
4812                 r_refdef.stats.entities++;
4813                 if (ent->model && ent->model->Draw != NULL)
4814                         ent->model->Draw(ent);
4815                 else
4816                         R_DrawNoModel(ent);
4817         }
4818 }
4819
4820 static void R_DrawModelsDepth(void)
4821 {
4822         int i;
4823         entity_render_t *ent;
4824
4825         for (i = 0;i < r_refdef.scene.numentities;i++)
4826         {
4827                 if (!r_refdef.viewcache.entityvisible[i])
4828                         continue;
4829                 ent = r_refdef.scene.entities[i];
4830                 if (ent->model && ent->model->DrawDepth != NULL)
4831                         ent->model->DrawDepth(ent);
4832         }
4833 }
4834
4835 static void R_DrawModelsDebug(void)
4836 {
4837         int i;
4838         entity_render_t *ent;
4839
4840         for (i = 0;i < r_refdef.scene.numentities;i++)
4841         {
4842                 if (!r_refdef.viewcache.entityvisible[i])
4843                         continue;
4844                 ent = r_refdef.scene.entities[i];
4845                 if (ent->model && ent->model->DrawDebug != NULL)
4846                         ent->model->DrawDebug(ent);
4847         }
4848 }
4849
4850 static void R_DrawModelsAddWaterPlanes(void)
4851 {
4852         int i;
4853         entity_render_t *ent;
4854
4855         for (i = 0;i < r_refdef.scene.numentities;i++)
4856         {
4857                 if (!r_refdef.viewcache.entityvisible[i])
4858                         continue;
4859                 ent = r_refdef.scene.entities[i];
4860                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4861                         ent->model->DrawAddWaterPlanes(ent);
4862         }
4863 }
4864
4865 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4866 {
4867         if (r_hdr_irisadaptation.integer)
4868         {
4869                 vec3_t ambient;
4870                 vec3_t diffuse;
4871                 vec3_t diffusenormal;
4872                 vec_t brightness;
4873                 vec_t goal;
4874                 vec_t adjust;
4875                 vec_t current;
4876                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4877                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4878                 brightness = max(0.0000001f, brightness);
4879                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4880                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4881                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4882                 current = r_hdr_irisadaptation_value.value;
4883                 if (current < goal)
4884                         current = min(current + adjust, goal);
4885                 else if (current > goal)
4886                         current = max(current - adjust, goal);
4887                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4888                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4889         }
4890         else if (r_hdr_irisadaptation_value.value != 1.0f)
4891                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4892 }
4893
4894 static void R_View_SetFrustum(const int *scissor)
4895 {
4896         int i;
4897         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4898         vec3_t forward, left, up, origin, v;
4899
4900         if(scissor)
4901         {
4902                 // flipped x coordinates (because x points left here)
4903                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4904                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4905
4906                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4907                 switch(vid.renderpath)
4908                 {
4909                         case RENDERPATH_D3D9:
4910                         case RENDERPATH_D3D10:
4911                         case RENDERPATH_D3D11:
4912                         case RENDERPATH_SOFT:
4913                                 // non-flipped y coordinates
4914                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4915                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4916                                 break;
4917                         case RENDERPATH_GL11:
4918                         case RENDERPATH_GL13:
4919                         case RENDERPATH_GL20:
4920                         case RENDERPATH_GLES2:
4921                                 // non-flipped y coordinates
4922                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4923                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4924                                 break;
4925                 }
4926         }
4927
4928         // we can't trust r_refdef.view.forward and friends in reflected scenes
4929         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4930
4931 #if 0
4932         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4933         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4934         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4935         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4936         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4937         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4938         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4939         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4940         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4941         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4942         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4943         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4944 #endif
4945
4946 #if 0
4947         zNear = r_refdef.nearclip;
4948         nudge = 1.0 - 1.0 / (1<<23);
4949         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4950         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4951         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4952         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4953         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4954         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4955         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4956         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4957 #endif
4958
4959
4960
4961 #if 0
4962         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4963         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4964         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4965         r_refdef.view.frustum[0].dist = m[15] - m[12];
4966
4967         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4968         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4969         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4970         r_refdef.view.frustum[1].dist = m[15] + m[12];
4971
4972         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4973         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4974         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4975         r_refdef.view.frustum[2].dist = m[15] - m[13];
4976
4977         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4978         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4979         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4980         r_refdef.view.frustum[3].dist = m[15] + m[13];
4981
4982         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4983         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4984         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4985         r_refdef.view.frustum[4].dist = m[15] - m[14];
4986
4987         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4988         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4989         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4990         r_refdef.view.frustum[5].dist = m[15] + m[14];
4991 #endif
4992
4993         if (r_refdef.view.useperspective)
4994         {
4995                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4996                 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]);
4997                 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]);
4998                 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]);
4999                 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]);
5000
5001                 // then the normals from the corners relative to origin
5002                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5003                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5004                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5005                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5006
5007                 // in a NORMAL view, forward cross left == up
5008                 // in a REFLECTED view, forward cross left == down
5009                 // so our cross products above need to be adjusted for a left handed coordinate system
5010                 CrossProduct(forward, left, v);
5011                 if(DotProduct(v, up) < 0)
5012                 {
5013                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5014                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5015                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5016                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5017                 }
5018
5019                 // Leaving those out was a mistake, those were in the old code, and they
5020                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5021                 // I couldn't reproduce it after adding those normalizations. --blub
5022                 VectorNormalize(r_refdef.view.frustum[0].normal);
5023                 VectorNormalize(r_refdef.view.frustum[1].normal);
5024                 VectorNormalize(r_refdef.view.frustum[2].normal);
5025                 VectorNormalize(r_refdef.view.frustum[3].normal);
5026
5027                 // make the corners absolute
5028                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5029                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5030                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5031                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5032
5033                 // one more normal
5034                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5035
5036                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5037                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5038                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5039                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5040                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5041         }
5042         else
5043         {
5044                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5045                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5046                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5047                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5048                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5049                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5050                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5051                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5052                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5053                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5054         }
5055         r_refdef.view.numfrustumplanes = 5;
5056
5057         if (r_refdef.view.useclipplane)
5058         {
5059                 r_refdef.view.numfrustumplanes = 6;
5060                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5061         }
5062
5063         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5064                 PlaneClassify(r_refdef.view.frustum + i);
5065
5066         // LordHavoc: note to all quake engine coders, Quake had a special case
5067         // for 90 degrees which assumed a square view (wrong), so I removed it,
5068         // Quake2 has it disabled as well.
5069
5070         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5071         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5072         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5073         //PlaneClassify(&frustum[0]);
5074
5075         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5076         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5077         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5078         //PlaneClassify(&frustum[1]);
5079
5080         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5081         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5082         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5083         //PlaneClassify(&frustum[2]);
5084
5085         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5086         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5087         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5088         //PlaneClassify(&frustum[3]);
5089
5090         // nearclip plane
5091         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5092         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5093         //PlaneClassify(&frustum[4]);
5094 }
5095
5096 void R_View_UpdateWithScissor(const int *myscissor)
5097 {
5098         R_Main_ResizeViewCache();
5099         R_View_SetFrustum(myscissor);
5100         R_View_WorldVisibility(r_refdef.view.useclipplane);
5101         R_View_UpdateEntityVisible();
5102         R_View_UpdateEntityLighting();
5103 }
5104
5105 void R_View_Update(void)
5106 {
5107         R_Main_ResizeViewCache();
5108         R_View_SetFrustum(NULL);
5109         R_View_WorldVisibility(r_refdef.view.useclipplane);
5110         R_View_UpdateEntityVisible();
5111         R_View_UpdateEntityLighting();
5112 }
5113
5114 void R_SetupView(qboolean allowwaterclippingplane)
5115 {
5116         const float *customclipplane = NULL;
5117         float plane[4];
5118         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5119         {
5120                 // LordHavoc: couldn't figure out how to make this approach the
5121                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5122                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5123                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5124                         dist = r_refdef.view.clipplane.dist;
5125                 plane[0] = r_refdef.view.clipplane.normal[0];
5126                 plane[1] = r_refdef.view.clipplane.normal[1];
5127                 plane[2] = r_refdef.view.clipplane.normal[2];
5128                 plane[3] = dist;
5129                 customclipplane = plane;
5130         }
5131
5132         if (!r_refdef.view.useperspective)
5133                 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);
5134         else if (vid.stencil && r_useinfinitefarclip.integer)
5135                 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);
5136         else
5137                 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);
5138         R_SetViewport(&r_refdef.view.viewport);
5139 }
5140
5141 void R_EntityMatrix(const matrix4x4_t *matrix)
5142 {
5143         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5144         {
5145                 gl_modelmatrixchanged = false;
5146                 gl_modelmatrix = *matrix;
5147                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5148                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5149                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5150                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5151                 CHECKGLERROR
5152                 switch(vid.renderpath)
5153                 {
5154                 case RENDERPATH_D3D9:
5155 #ifdef SUPPORTD3D
5156                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5157                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5158 #endif
5159                         break;
5160                 case RENDERPATH_D3D10:
5161                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5162                         break;
5163                 case RENDERPATH_D3D11:
5164                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5165                         break;
5166                 case RENDERPATH_GL13:
5167                 case RENDERPATH_GL11:
5168                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5169                         break;
5170                 case RENDERPATH_SOFT:
5171                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5172                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5173                         break;
5174                 case RENDERPATH_GL20:
5175                 case RENDERPATH_GLES2:
5176                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5177                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5178                         break;
5179                 }
5180         }
5181 }
5182
5183 void R_ResetViewRendering2D(void)
5184 {
5185         r_viewport_t viewport;
5186         DrawQ_Finish();
5187
5188         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5189         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);
5190         R_SetViewport(&viewport);
5191         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5192         GL_Color(1, 1, 1, 1);
5193         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5194         GL_BlendFunc(GL_ONE, GL_ZERO);
5195         GL_ScissorTest(false);
5196         GL_DepthMask(false);
5197         GL_DepthRange(0, 1);
5198         GL_DepthTest(false);
5199         GL_DepthFunc(GL_LEQUAL);
5200         R_EntityMatrix(&identitymatrix);
5201         R_Mesh_ResetTextureState();
5202         GL_PolygonOffset(0, 0);
5203         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5204         switch(vid.renderpath)
5205         {
5206         case RENDERPATH_GL11:
5207         case RENDERPATH_GL13:
5208         case RENDERPATH_GL20:
5209         case RENDERPATH_GLES2:
5210                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5211                 break;
5212         case RENDERPATH_D3D9:
5213         case RENDERPATH_D3D10:
5214         case RENDERPATH_D3D11:
5215         case RENDERPATH_SOFT:
5216                 break;
5217         }
5218         GL_CullFace(GL_NONE);
5219 }
5220
5221 void R_ResetViewRendering3D(void)
5222 {
5223         DrawQ_Finish();
5224
5225         R_SetupView(true);
5226         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5227         GL_Color(1, 1, 1, 1);
5228         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5229         GL_BlendFunc(GL_ONE, GL_ZERO);
5230         GL_ScissorTest(true);
5231         GL_DepthMask(true);
5232         GL_DepthRange(0, 1);
5233         GL_DepthTest(true);
5234         GL_DepthFunc(GL_LEQUAL);
5235         R_EntityMatrix(&identitymatrix);
5236         R_Mesh_ResetTextureState();
5237         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5238         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5239         switch(vid.renderpath)
5240         {
5241         case RENDERPATH_GL11:
5242         case RENDERPATH_GL13:
5243         case RENDERPATH_GL20:
5244         case RENDERPATH_GLES2:
5245                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5246                 break;
5247         case RENDERPATH_D3D9:
5248         case RENDERPATH_D3D10:
5249         case RENDERPATH_D3D11:
5250         case RENDERPATH_SOFT:
5251                 break;
5252         }
5253         GL_CullFace(r_refdef.view.cullface_back);
5254 }
5255
5256 /*
5257 ================
5258 R_RenderView_UpdateViewVectors
5259 ================
5260 */
5261 static void R_RenderView_UpdateViewVectors(void)
5262 {
5263         // break apart the view matrix into vectors for various purposes
5264         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5265         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5266         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5267         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5268         // make an inverted copy of the view matrix for tracking sprites
5269         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5270 }
5271
5272 void R_RenderScene(void);
5273 void R_RenderWaterPlanes(void);
5274
5275 static void R_Water_StartFrame(void)
5276 {
5277         int i;
5278         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5279         r_waterstate_waterplane_t *p;
5280
5281         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5282                 return;
5283
5284         switch(vid.renderpath)
5285         {
5286         case RENDERPATH_GL20:
5287         case RENDERPATH_D3D9:
5288         case RENDERPATH_D3D10:
5289         case RENDERPATH_D3D11:
5290         case RENDERPATH_SOFT:
5291         case RENDERPATH_GLES2:
5292                 break;
5293         case RENDERPATH_GL13:
5294         case RENDERPATH_GL11:
5295                 return;
5296         }
5297
5298         // set waterwidth and waterheight to the water resolution that will be
5299         // used (often less than the screen resolution for faster rendering)
5300         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5301         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5302
5303         // calculate desired texture sizes
5304         // can't use water if the card does not support the texture size
5305         if (!r_water.integer || r_showsurfaces.integer)
5306                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5307         else if (vid.support.arb_texture_non_power_of_two)
5308         {
5309                 texturewidth = waterwidth;
5310                 textureheight = waterheight;
5311                 camerawidth = waterwidth;
5312                 cameraheight = waterheight;
5313         }
5314         else
5315         {
5316                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5317                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5318                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5319                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5320         }
5321
5322         // allocate textures as needed
5323         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5324         {
5325                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5326                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5327                 {
5328                         if (p->texture_refraction)
5329                                 R_FreeTexture(p->texture_refraction);
5330                         p->texture_refraction = NULL;
5331                         if (p->texture_reflection)
5332                                 R_FreeTexture(p->texture_reflection);
5333                         p->texture_reflection = NULL;
5334                         if (p->texture_camera)
5335                                 R_FreeTexture(p->texture_camera);
5336                         p->texture_camera = NULL;
5337                 }
5338                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5339                 r_waterstate.texturewidth = texturewidth;
5340                 r_waterstate.textureheight = textureheight;
5341                 r_waterstate.camerawidth = camerawidth;
5342                 r_waterstate.cameraheight = cameraheight;
5343         }
5344
5345         if (r_waterstate.texturewidth)
5346         {
5347                 r_waterstate.enabled = true;
5348
5349                 // when doing a reduced render (HDR) we want to use a smaller area
5350                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5351                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5352
5353                 // set up variables that will be used in shader setup
5354                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5355                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5356                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5357                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5358         }
5359
5360         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5361         r_waterstate.numwaterplanes = 0;
5362 }
5363
5364 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5365 {
5366         int triangleindex, planeindex;
5367         const int *e;
5368         vec3_t vert[3];
5369         vec3_t normal;
5370         vec3_t center;
5371         mplane_t plane;
5372         r_waterstate_waterplane_t *p;
5373         texture_t *t = R_GetCurrentTexture(surface->texture);
5374
5375         // just use the first triangle with a valid normal for any decisions
5376         VectorClear(normal);
5377         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5378         {
5379                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5380                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5381                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5382                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5383                 if (VectorLength2(normal) >= 0.001)
5384                         break;
5385         }
5386
5387         VectorCopy(normal, plane.normal);
5388         VectorNormalize(plane.normal);
5389         plane.dist = DotProduct(vert[0], plane.normal);
5390         PlaneClassify(&plane);
5391         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5392         {
5393                 // skip backfaces (except if nocullface is set)
5394                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5395                         return;
5396                 VectorNegate(plane.normal, plane.normal);
5397                 plane.dist *= -1;
5398                 PlaneClassify(&plane);
5399         }
5400
5401
5402         // find a matching plane if there is one
5403         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5404                 if(p->camera_entity == t->camera_entity)
5405                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5406                                 break;
5407         if (planeindex >= r_waterstate.maxwaterplanes)
5408                 return; // nothing we can do, out of planes
5409
5410         // if this triangle does not fit any known plane rendered this frame, add one
5411         if (planeindex >= r_waterstate.numwaterplanes)
5412         {
5413                 // store the new plane
5414                 r_waterstate.numwaterplanes++;
5415                 p->plane = plane;
5416                 // clear materialflags and pvs
5417                 p->materialflags = 0;
5418                 p->pvsvalid = false;
5419                 p->camera_entity = t->camera_entity;
5420                 VectorCopy(surface->mins, p->mins);
5421                 VectorCopy(surface->maxs, p->maxs);
5422         }
5423         else
5424         {
5425                 // merge mins/maxs
5426                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5427                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5428                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5429                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5430                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5431                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5432         }
5433         // merge this surface's materialflags into the waterplane
5434         p->materialflags |= t->currentmaterialflags;
5435         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5436         {
5437                 // merge this surface's PVS into the waterplane
5438                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5439                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5440                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5441                 {
5442                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5443                         p->pvsvalid = true;
5444                 }
5445         }
5446 }
5447
5448 static void R_Water_ProcessPlanes(void)
5449 {
5450         int myscissor[4];
5451         r_refdef_view_t originalview;
5452         r_refdef_view_t myview;
5453         int planeindex;
5454         r_waterstate_waterplane_t *p;
5455         vec3_t visorigin;
5456
5457         originalview = r_refdef.view;
5458
5459         // make sure enough textures are allocated
5460         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5461         {
5462                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5463                 {
5464                         if (!p->texture_refraction)
5465                                 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);
5466                         if (!p->texture_refraction)
5467                                 goto error;
5468                 }
5469                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5470                 {
5471                         if (!p->texture_camera)
5472                                 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);
5473                         if (!p->texture_camera)
5474                                 goto error;
5475                 }
5476
5477                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5478                 {
5479                         if (!p->texture_reflection)
5480                                 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);
5481                         if (!p->texture_reflection)
5482                                 goto error;
5483                 }
5484         }
5485
5486         // render views
5487         r_refdef.view = originalview;
5488         r_refdef.view.showdebug = false;
5489         r_refdef.view.width = r_waterstate.waterwidth;
5490         r_refdef.view.height = r_waterstate.waterheight;
5491         r_refdef.view.useclipplane = true;
5492         myview = r_refdef.view;
5493         r_waterstate.renderingscene = true;
5494         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5495         {
5496                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
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                         // render reflected scene and copy into texture
5507                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5508                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5509                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5510                         r_refdef.view.clipplane = p->plane;
5511
5512                         // reverse the cullface settings for this render
5513                         r_refdef.view.cullface_front = GL_FRONT;
5514                         r_refdef.view.cullface_back = GL_BACK;
5515                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5516                         {
5517                                 r_refdef.view.usecustompvs = true;
5518                                 if (p->pvsvalid)
5519                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5520                                 else
5521                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5522                         }
5523
5524                         R_ResetViewRendering3D();
5525                         R_ClearScreen(r_refdef.fogenabled);
5526                         if(r_water_scissormode.integer & 2)
5527                                 R_View_UpdateWithScissor(myscissor);
5528                         else
5529                                 R_View_Update();
5530                         if(r_water_scissormode.integer & 1)
5531                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5532                         R_RenderScene();
5533
5534                         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);
5535                 }
5536
5537                 // render the normal view scene and copy into texture
5538                 // (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)
5539                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5540                 {
5541                         r_refdef.view = myview;
5542                         if(r_water_scissormode.integer)
5543                         {
5544                                 R_SetupView(true);
5545                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5546                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5547                         }
5548
5549                         r_waterstate.renderingrefraction = true;
5550
5551                         r_refdef.view.clipplane = p->plane;
5552                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5553                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5554
5555                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5556                         {
5557                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5558                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5559                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5560                                 R_RenderView_UpdateViewVectors();
5561                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5562                                 {
5563                                         r_refdef.view.usecustompvs = true;
5564                                         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);
5565                                 }
5566                         }
5567
5568                         PlaneClassify(&r_refdef.view.clipplane);
5569
5570                         R_ResetViewRendering3D();
5571                         R_ClearScreen(r_refdef.fogenabled);
5572                         if(r_water_scissormode.integer & 2)
5573                                 R_View_UpdateWithScissor(myscissor);
5574                         else
5575                                 R_View_Update();
5576                         if(r_water_scissormode.integer & 1)
5577                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5578                         R_RenderScene();
5579
5580                         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);
5581                         r_waterstate.renderingrefraction = false;
5582                 }
5583                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5584                 {
5585                         r_refdef.view = myview;
5586
5587                         r_refdef.view.clipplane = p->plane;
5588                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5589                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5590
5591                         r_refdef.view.width = r_waterstate.camerawidth;
5592                         r_refdef.view.height = r_waterstate.cameraheight;
5593                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5594                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5595
5596                         if(p->camera_entity)
5597                         {
5598                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5599                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5600                         }
5601
5602                         // note: all of the view is used for displaying... so
5603                         // there is no use in scissoring
5604
5605                         // reverse the cullface settings for this render
5606                         r_refdef.view.cullface_front = GL_FRONT;
5607                         r_refdef.view.cullface_back = GL_BACK;
5608                         // also reverse the view matrix
5609                         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
5610                         R_RenderView_UpdateViewVectors();
5611                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5612                         {
5613                                 r_refdef.view.usecustompvs = true;
5614                                 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);
5615                         }
5616                         
5617                         // camera needs no clipplane
5618                         r_refdef.view.useclipplane = false;
5619
5620                         PlaneClassify(&r_refdef.view.clipplane);
5621
5622                         R_ResetViewRendering3D();
5623                         R_ClearScreen(r_refdef.fogenabled);
5624                         R_View_Update();
5625                         R_RenderScene();
5626
5627                         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);
5628                         r_waterstate.renderingrefraction = false;
5629                 }
5630
5631         }
5632         r_waterstate.renderingscene = false;
5633         r_refdef.view = originalview;
5634         R_ResetViewRendering3D();
5635         R_ClearScreen(r_refdef.fogenabled);
5636         R_View_Update();
5637         return;
5638 error:
5639         r_refdef.view = originalview;
5640         r_waterstate.renderingscene = false;
5641         Cvar_SetValueQuick(&r_water, 0);
5642         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5643         return;
5644 }
5645
5646 void R_Bloom_StartFrame(void)
5647 {
5648         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5649
5650         switch(vid.renderpath)
5651         {
5652         case RENDERPATH_GL20:
5653         case RENDERPATH_D3D9:
5654         case RENDERPATH_D3D10:
5655         case RENDERPATH_D3D11:
5656         case RENDERPATH_SOFT:
5657         case RENDERPATH_GLES2:
5658                 break;
5659         case RENDERPATH_GL13:
5660         case RENDERPATH_GL11:
5661                 return;
5662         }
5663
5664         // set bloomwidth and bloomheight to the bloom resolution that will be
5665         // used (often less than the screen resolution for faster rendering)
5666         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5667         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5668         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5669         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5670         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5671
5672         // calculate desired texture sizes
5673         if (vid.support.arb_texture_non_power_of_two)
5674         {
5675                 screentexturewidth = r_refdef.view.width;
5676                 screentextureheight = r_refdef.view.height;
5677                 bloomtexturewidth = r_bloomstate.bloomwidth;
5678                 bloomtextureheight = r_bloomstate.bloomheight;
5679         }
5680         else
5681         {
5682                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5683                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5684                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5685                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5686         }
5687
5688         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))
5689         {
5690                 Cvar_SetValueQuick(&r_hdr, 0);
5691                 Cvar_SetValueQuick(&r_bloom, 0);
5692                 Cvar_SetValueQuick(&r_motionblur, 0);
5693                 Cvar_SetValueQuick(&r_damageblur, 0);
5694         }
5695
5696         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)))
5697                 screentexturewidth = screentextureheight = 0;
5698         if (!r_hdr.integer && !r_bloom.integer)
5699                 bloomtexturewidth = bloomtextureheight = 0;
5700
5701         // allocate textures as needed
5702         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5703         {
5704                 if (r_bloomstate.texture_screen)
5705                         R_FreeTexture(r_bloomstate.texture_screen);
5706                 r_bloomstate.texture_screen = NULL;
5707                 r_bloomstate.screentexturewidth = screentexturewidth;
5708                 r_bloomstate.screentextureheight = screentextureheight;
5709                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5710                         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);
5711         }
5712         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5713         {
5714                 if (r_bloomstate.texture_bloom)
5715                         R_FreeTexture(r_bloomstate.texture_bloom);
5716                 r_bloomstate.texture_bloom = NULL;
5717                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5718                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5719                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5720                         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);
5721         }
5722
5723         // when doing a reduced render (HDR) we want to use a smaller area
5724         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5725         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5726         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5727         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5728         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5729
5730         // set up a texcoord array for the full resolution screen image
5731         // (we have to keep this around to copy back during final render)
5732         r_bloomstate.screentexcoord2f[0] = 0;
5733         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5734         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5735         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5736         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5737         r_bloomstate.screentexcoord2f[5] = 0;
5738         r_bloomstate.screentexcoord2f[6] = 0;
5739         r_bloomstate.screentexcoord2f[7] = 0;
5740
5741         // set up a texcoord array for the reduced resolution bloom image
5742         // (which will be additive blended over the screen image)
5743         r_bloomstate.bloomtexcoord2f[0] = 0;
5744         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5745         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5746         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5747         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5748         r_bloomstate.bloomtexcoord2f[5] = 0;
5749         r_bloomstate.bloomtexcoord2f[6] = 0;
5750         r_bloomstate.bloomtexcoord2f[7] = 0;
5751
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                 break;
5760         case RENDERPATH_D3D9:
5761         case RENDERPATH_D3D10:
5762         case RENDERPATH_D3D11:
5763                 {
5764                         int i;
5765                         for (i = 0;i < 4;i++)
5766                         {
5767                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5768                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5769                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5770                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5771                         }
5772                 }
5773                 break;
5774         }
5775
5776         if (r_hdr.integer || r_bloom.integer)
5777         {
5778                 r_bloomstate.enabled = true;
5779                 r_bloomstate.hdr = r_hdr.integer != 0;
5780         }
5781
5782         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);
5783 }
5784
5785 void R_Bloom_CopyBloomTexture(float colorscale)
5786 {
5787         r_refdef.stats.bloom++;
5788
5789         // scale down screen texture to the bloom texture size
5790         CHECKGLERROR
5791         R_SetViewport(&r_bloomstate.viewport);
5792         GL_BlendFunc(GL_ONE, GL_ZERO);
5793         GL_Color(colorscale, colorscale, colorscale, 1);
5794         // 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...
5795         switch(vid.renderpath)
5796         {
5797         case RENDERPATH_GL11:
5798         case RENDERPATH_GL13:
5799         case RENDERPATH_GL20:
5800         case RENDERPATH_SOFT:
5801         case RENDERPATH_GLES2:
5802                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5803                 break;
5804         case RENDERPATH_D3D9:
5805         case RENDERPATH_D3D10:
5806         case RENDERPATH_D3D11:
5807                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5808                 break;
5809         }
5810         // TODO: do boxfilter scale-down in shader?
5811         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5812         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5813         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5814
5815         // we now have a bloom image in the framebuffer
5816         // copy it into the bloom image texture for later processing
5817         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);
5818         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5819 }
5820
5821 void R_Bloom_CopyHDRTexture(void)
5822 {
5823         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);
5824         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5825 }
5826
5827 void R_Bloom_MakeTexture(void)
5828 {
5829         int x, range, dir;
5830         float xoffset, yoffset, r, brighten;
5831
5832         r_refdef.stats.bloom++;
5833
5834         R_ResetViewRendering2D();
5835
5836         // we have a bloom image in the framebuffer
5837         CHECKGLERROR
5838         R_SetViewport(&r_bloomstate.viewport);
5839
5840         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5841         {
5842                 x *= 2;
5843                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5844                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5845                 GL_Color(r,r,r,1);
5846                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5847                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5848                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5849                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5850
5851                 // copy the vertically blurred bloom view to a texture
5852                 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);
5853                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5854         }
5855
5856         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5857         brighten = r_bloom_brighten.value;
5858         if (r_hdr.integer)
5859                 brighten *= r_hdr_range.value;
5860         brighten = sqrt(brighten);
5861         if(range >= 1)
5862                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5863         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5864
5865         for (dir = 0;dir < 2;dir++)
5866         {
5867                 // blend on at multiple vertical offsets to achieve a vertical blur
5868                 // TODO: do offset blends using GLSL
5869                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5870                 GL_BlendFunc(GL_ONE, GL_ZERO);
5871                 for (x = -range;x <= range;x++)
5872                 {
5873                         if (!dir){xoffset = 0;yoffset = x;}
5874                         else {xoffset = x;yoffset = 0;}
5875                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5876                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5877                         // compute a texcoord array with the specified x and y offset
5878                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5879                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5880                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5881                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5882                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5883                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5884                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5885                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5886                         // this r value looks like a 'dot' particle, fading sharply to
5887                         // black at the edges
5888                         // (probably not realistic but looks good enough)
5889                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5890                         //r = brighten/(range*2+1);
5891                         r = brighten / (range * 2 + 1);
5892                         if(range >= 1)
5893                                 r *= (1 - x*x/(float)(range*range));
5894                         GL_Color(r, r, r, 1);
5895                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5896                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5897                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5898                         GL_BlendFunc(GL_ONE, GL_ONE);
5899                 }
5900
5901                 // copy the vertically blurred bloom view to a texture
5902                 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);
5903                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5904         }
5905 }
5906
5907 void R_HDR_RenderBloomTexture(void)
5908 {
5909         int oldwidth, oldheight;
5910         float oldcolorscale;
5911         qboolean oldwaterstate;
5912
5913         oldwaterstate = r_waterstate.enabled;
5914         oldcolorscale = r_refdef.view.colorscale;
5915         oldwidth = r_refdef.view.width;
5916         oldheight = r_refdef.view.height;
5917         r_refdef.view.width = r_bloomstate.bloomwidth;
5918         r_refdef.view.height = r_bloomstate.bloomheight;
5919
5920         if(r_hdr.integer < 2)
5921                 r_waterstate.enabled = false;
5922
5923         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5924         // TODO: add exposure compensation features
5925         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5926
5927         r_refdef.view.showdebug = false;
5928         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5929
5930         R_ResetViewRendering3D();
5931
5932         R_ClearScreen(r_refdef.fogenabled);
5933         if (r_timereport_active)
5934                 R_TimeReport("HDRclear");
5935
5936         R_View_Update();
5937         if (r_timereport_active)
5938                 R_TimeReport("visibility");
5939
5940         // only do secondary renders with HDR if r_hdr is 2 or higher
5941         r_waterstate.numwaterplanes = 0;
5942         if (r_waterstate.enabled)
5943                 R_RenderWaterPlanes();
5944
5945         r_refdef.view.showdebug = true;
5946         R_RenderScene();
5947         r_waterstate.numwaterplanes = 0;
5948
5949         R_ResetViewRendering2D();
5950
5951         R_Bloom_CopyHDRTexture();
5952         R_Bloom_MakeTexture();
5953
5954         // restore the view settings
5955         r_waterstate.enabled = oldwaterstate;
5956         r_refdef.view.width = oldwidth;
5957         r_refdef.view.height = oldheight;
5958         r_refdef.view.colorscale = oldcolorscale;
5959
5960         R_ResetViewRendering3D();
5961
5962         R_ClearScreen(r_refdef.fogenabled);
5963         if (r_timereport_active)
5964                 R_TimeReport("viewclear");
5965 }
5966
5967 static void R_BlendView(void)
5968 {
5969         unsigned int permutation;
5970         float uservecs[4][4];
5971
5972         switch (vid.renderpath)
5973         {
5974         case RENDERPATH_GL20:
5975         case RENDERPATH_D3D9:
5976         case RENDERPATH_D3D10:
5977         case RENDERPATH_D3D11:
5978         case RENDERPATH_SOFT:
5979         case RENDERPATH_GLES2:
5980                 permutation =
5981                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5982                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5983                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5984                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5985                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5986
5987                 if (r_bloomstate.texture_screen)
5988                 {
5989                         // make sure the buffer is available
5990                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5991
5992                         R_ResetViewRendering2D();
5993
5994                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5995                         {
5996                                 // declare variables
5997                                 float speed;
5998                                 static float avgspeed;
5999
6000                                 speed = VectorLength(cl.movement_velocity);
6001
6002                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6003                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6004
6005                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6006                                 speed = bound(0, speed, 1);
6007                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6008
6009                                 // calculate values into a standard alpha
6010                                 cl.motionbluralpha = 1 - exp(-
6011                                                 (
6012                                                  (r_motionblur.value * speed / 80)
6013                                                  +
6014                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6015                                                 )
6016                                                 /
6017                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6018                                            );
6019
6020                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6021                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6022                                 // apply the blur
6023                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6024                                 {
6025                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6026                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6027                                         switch(vid.renderpath)
6028                                         {
6029                                         case RENDERPATH_GL11:
6030                                         case RENDERPATH_GL13:
6031                                         case RENDERPATH_GL20:
6032                                         case RENDERPATH_SOFT:
6033                                         case RENDERPATH_GLES2:
6034                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6035                                                 break;
6036                                         case RENDERPATH_D3D9:
6037                                         case RENDERPATH_D3D10:
6038                                         case RENDERPATH_D3D11:
6039                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6040                                                 break;
6041                                         }
6042                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6043                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6044                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6045                                 }
6046                         }
6047
6048                         // copy view into the screen texture
6049                         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);
6050                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6051                 }
6052                 else if (!r_bloomstate.texture_bloom)
6053                 {
6054                         // we may still have to do view tint...
6055                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6056                         {
6057                                 // apply a color tint to the whole view
6058                                 R_ResetViewRendering2D();
6059                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6060                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6061                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6062                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6063                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6064                         }
6065                         break; // no screen processing, no bloom, skip it
6066                 }
6067
6068                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6069                 {
6070                         // render simple bloom effect
6071                         // copy the screen and shrink it and darken it for the bloom process
6072                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6073                         // make the bloom texture
6074                         R_Bloom_MakeTexture();
6075                 }
6076
6077 #if _MSC_VER >= 1400
6078 #define sscanf sscanf_s
6079 #endif
6080                 memset(uservecs, 0, sizeof(uservecs));
6081                 if (r_glsl_postprocess_uservec1_enable.integer)
6082                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6083                 if (r_glsl_postprocess_uservec2_enable.integer)
6084                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6085                 if (r_glsl_postprocess_uservec3_enable.integer)
6086                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6087                 if (r_glsl_postprocess_uservec4_enable.integer)
6088                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6089
6090                 R_ResetViewRendering2D();
6091                 GL_Color(1, 1, 1, 1);
6092                 GL_BlendFunc(GL_ONE, GL_ZERO);
6093
6094                 switch(vid.renderpath)
6095                 {
6096                 case RENDERPATH_GL20:
6097                 case RENDERPATH_GLES2:
6098                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6099                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6100                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6101                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6102                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6103                         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]);
6104                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6105                         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]);
6106                         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]);
6107                         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]);
6108                         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]);
6109                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6110                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6111                         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);
6112                         break;
6113                 case RENDERPATH_D3D9:
6114 #ifdef SUPPORTD3D
6115                         // 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...
6116                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6117                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6118                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6119                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6120                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6121                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6122                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6123                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6124                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6125                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6126                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6127                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6128                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6129                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6130 #endif
6131                         break;
6132                 case RENDERPATH_D3D10:
6133                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6134                         break;
6135                 case RENDERPATH_D3D11:
6136                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6137                         break;
6138                 case RENDERPATH_SOFT:
6139                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6140                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6141                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6142                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6143                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6144                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6145                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6146                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6147                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6148                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6149                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6150                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6151                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6152                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6153                         break;
6154                 default:
6155                         break;
6156                 }
6157                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6158                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6159                 break;
6160         case RENDERPATH_GL13:
6161         case RENDERPATH_GL11:
6162                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6163                 {
6164                         // apply a color tint to the whole view
6165                         R_ResetViewRendering2D();
6166                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6167                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6168                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6170                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6171                 }
6172                 break;
6173         }
6174 }
6175
6176 matrix4x4_t r_waterscrollmatrix;
6177
6178 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6179 {
6180         if (r_refdef.fog_density)
6181         {
6182                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6183                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6184                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6185
6186                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6187                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6188                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6189                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6190
6191                 {
6192                         vec3_t fogvec;
6193                         VectorCopy(r_refdef.fogcolor, fogvec);
6194                         //   color.rgb *= ContrastBoost * SceneBrightness;
6195                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6196                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6197                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6198                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6199                 }
6200         }
6201 }
6202
6203 void R_UpdateVariables(void)
6204 {
6205         R_Textures_Frame();
6206
6207         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6208
6209         r_refdef.farclip = r_farclip_base.value;
6210         if (r_refdef.scene.worldmodel)
6211                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6212         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6213
6214         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6215                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6216         r_refdef.polygonfactor = 0;
6217         r_refdef.polygonoffset = 0;
6218         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6219         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6220
6221         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6222         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6223         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6224         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6225         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6226         if (FAKELIGHT_ENABLED)
6227         {
6228                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6229         }
6230         if (r_showsurfaces.integer)
6231         {
6232                 r_refdef.scene.rtworld = false;
6233                 r_refdef.scene.rtworldshadows = false;
6234                 r_refdef.scene.rtdlight = false;
6235                 r_refdef.scene.rtdlightshadows = false;
6236                 r_refdef.lightmapintensity = 0;
6237         }
6238
6239         if (gamemode == GAME_NEHAHRA)
6240         {
6241                 if (gl_fogenable.integer)
6242                 {
6243                         r_refdef.oldgl_fogenable = true;
6244                         r_refdef.fog_density = gl_fogdensity.value;
6245                         r_refdef.fog_red = gl_fogred.value;
6246                         r_refdef.fog_green = gl_foggreen.value;
6247                         r_refdef.fog_blue = gl_fogblue.value;
6248                         r_refdef.fog_alpha = 1;
6249                         r_refdef.fog_start = 0;
6250                         r_refdef.fog_end = gl_skyclip.value;
6251                         r_refdef.fog_height = 1<<30;
6252                         r_refdef.fog_fadedepth = 128;
6253                 }
6254                 else if (r_refdef.oldgl_fogenable)
6255                 {
6256                         r_refdef.oldgl_fogenable = false;
6257                         r_refdef.fog_density = 0;
6258                         r_refdef.fog_red = 0;
6259                         r_refdef.fog_green = 0;
6260                         r_refdef.fog_blue = 0;
6261                         r_refdef.fog_alpha = 0;
6262                         r_refdef.fog_start = 0;
6263                         r_refdef.fog_end = 0;
6264                         r_refdef.fog_height = 1<<30;
6265                         r_refdef.fog_fadedepth = 128;
6266                 }
6267         }
6268
6269         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6270         r_refdef.fog_start = max(0, r_refdef.fog_start);
6271         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6272
6273         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6274
6275         if (r_refdef.fog_density && r_drawfog.integer)
6276         {
6277                 r_refdef.fogenabled = true;
6278                 // this is the point where the fog reaches 0.9986 alpha, which we
6279                 // consider a good enough cutoff point for the texture
6280                 // (0.9986 * 256 == 255.6)
6281                 if (r_fog_exp2.integer)
6282                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6283                 else
6284                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6285                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6286                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6287                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6288                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6289                         R_BuildFogHeightTexture();
6290                 // fog color was already set
6291                 // update the fog texture
6292                 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)
6293                         R_BuildFogTexture();
6294                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6295                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6296         }
6297         else
6298                 r_refdef.fogenabled = false;
6299
6300         switch(vid.renderpath)
6301         {
6302         case RENDERPATH_GL20:
6303         case RENDERPATH_D3D9:
6304         case RENDERPATH_D3D10:
6305         case RENDERPATH_D3D11:
6306         case RENDERPATH_SOFT:
6307         case RENDERPATH_GLES2:
6308                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6309                 {
6310                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6311                         {
6312                                 // build GLSL gamma texture
6313 #define RAMPWIDTH 256
6314                                 unsigned short ramp[RAMPWIDTH * 3];
6315                                 unsigned char rampbgr[RAMPWIDTH][4];
6316                                 int i;
6317
6318                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6319
6320                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6321                                 for(i = 0; i < RAMPWIDTH; ++i)
6322                                 {
6323                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6324                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6325                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6326                                         rampbgr[i][3] = 0;
6327                                 }
6328                                 if (r_texture_gammaramps)
6329                                 {
6330                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6331                                 }
6332                                 else
6333                                 {
6334                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6335                                 }
6336                         }
6337                 }
6338                 else
6339                 {
6340                         // remove GLSL gamma texture
6341                 }
6342                 break;
6343         case RENDERPATH_GL13:
6344         case RENDERPATH_GL11:
6345                 break;
6346         }
6347 }
6348
6349 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6350 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6351 /*
6352 ================
6353 R_SelectScene
6354 ================
6355 */
6356 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6357         if( scenetype != r_currentscenetype ) {
6358                 // store the old scenetype
6359                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6360                 r_currentscenetype = scenetype;
6361                 // move in the new scene
6362                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6363         }
6364 }
6365
6366 /*
6367 ================
6368 R_GetScenePointer
6369 ================
6370 */
6371 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6372 {
6373         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6374         if( scenetype == r_currentscenetype ) {
6375                 return &r_refdef.scene;
6376         } else {
6377                 return &r_scenes_store[ scenetype ];
6378         }
6379 }
6380
6381 /*
6382 ================
6383 R_RenderView
6384 ================
6385 */
6386 int dpsoftrast_test;
6387 void R_RenderView(void)
6388 {
6389         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6390
6391         dpsoftrast_test = r_test.integer;
6392
6393         if (r_timereport_active)
6394                 R_TimeReport("start");
6395         r_textureframe++; // used only by R_GetCurrentTexture
6396         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6397
6398         if(R_CompileShader_CheckStaticParms())
6399                 R_GLSL_Restart_f();
6400
6401         if (!r_drawentities.integer)
6402                 r_refdef.scene.numentities = 0;
6403
6404         R_AnimCache_ClearCache();
6405         R_FrameData_NewFrame();
6406
6407         /* adjust for stereo display */
6408         if(R_Stereo_Active())
6409         {
6410                 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);
6411                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6412         }
6413
6414         if (r_refdef.view.isoverlay)
6415         {
6416                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6417                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6418                 R_TimeReport("depthclear");
6419
6420                 r_refdef.view.showdebug = false;
6421
6422                 r_waterstate.enabled = false;
6423                 r_waterstate.numwaterplanes = 0;
6424
6425                 R_RenderScene();
6426
6427                 r_refdef.view.matrix = originalmatrix;
6428
6429                 CHECKGLERROR
6430                 return;
6431         }
6432
6433         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6434         {
6435                 r_refdef.view.matrix = originalmatrix;
6436                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6437         }
6438
6439         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6440
6441         R_RenderView_UpdateViewVectors();
6442
6443         R_Shadow_UpdateWorldLightSelection();
6444
6445         R_Bloom_StartFrame();
6446         R_Water_StartFrame();
6447
6448         CHECKGLERROR
6449         if (r_timereport_active)
6450                 R_TimeReport("viewsetup");
6451
6452         R_ResetViewRendering3D();
6453
6454         if (r_refdef.view.clear || r_refdef.fogenabled)
6455         {
6456                 R_ClearScreen(r_refdef.fogenabled);
6457                 if (r_timereport_active)
6458                         R_TimeReport("viewclear");
6459         }
6460         r_refdef.view.clear = true;
6461
6462         // this produces a bloom texture to be used in R_BlendView() later
6463         if (r_hdr.integer && r_bloomstate.bloomwidth)
6464         {
6465                 R_HDR_RenderBloomTexture();
6466                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6467                 r_textureframe++; // used only by R_GetCurrentTexture
6468         }
6469
6470         r_refdef.view.showdebug = true;
6471
6472         R_View_Update();
6473         if (r_timereport_active)
6474                 R_TimeReport("visibility");
6475
6476         r_waterstate.numwaterplanes = 0;
6477         if (r_waterstate.enabled)
6478                 R_RenderWaterPlanes();
6479
6480         R_RenderScene();
6481         r_waterstate.numwaterplanes = 0;
6482
6483         R_BlendView();
6484         if (r_timereport_active)
6485                 R_TimeReport("blendview");
6486
6487         GL_Scissor(0, 0, vid.width, vid.height);
6488         GL_ScissorTest(false);
6489
6490         r_refdef.view.matrix = originalmatrix;
6491
6492         CHECKGLERROR
6493 }
6494
6495 void R_RenderWaterPlanes(void)
6496 {
6497         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6498         {
6499                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6500                 if (r_timereport_active)
6501                         R_TimeReport("waterworld");
6502         }
6503
6504         // don't let sound skip if going slow
6505         if (r_refdef.scene.extraupdate)
6506                 S_ExtraUpdate ();
6507
6508         R_DrawModelsAddWaterPlanes();
6509         if (r_timereport_active)
6510                 R_TimeReport("watermodels");
6511
6512         if (r_waterstate.numwaterplanes)
6513         {
6514                 R_Water_ProcessPlanes();
6515                 if (r_timereport_active)
6516                         R_TimeReport("waterscenes");
6517         }
6518 }
6519
6520 extern void R_DrawLightningBeams (void);
6521 extern void VM_CL_AddPolygonsToMeshQueue (void);
6522 extern void R_DrawPortals (void);
6523 extern cvar_t cl_locs_show;
6524 static void R_DrawLocs(void);
6525 static void R_DrawEntityBBoxes(void);
6526 static void R_DrawModelDecals(void);
6527 extern void R_DrawModelShadows(void);
6528 extern void R_DrawModelShadowMaps(void);
6529 extern cvar_t cl_decals_newsystem;
6530 extern qboolean r_shadow_usingdeferredprepass;
6531 void R_RenderScene(void)
6532 {
6533         qboolean shadowmapping = false;
6534
6535         if (r_timereport_active)
6536                 R_TimeReport("beginscene");
6537
6538         r_refdef.stats.renders++;
6539
6540         R_UpdateFogColor();
6541
6542         // don't let sound skip if going slow
6543         if (r_refdef.scene.extraupdate)
6544                 S_ExtraUpdate ();
6545
6546         R_MeshQueue_BeginScene();
6547
6548         R_SkyStartFrame();
6549
6550         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);
6551
6552         if (r_timereport_active)
6553                 R_TimeReport("skystartframe");
6554
6555         if (cl.csqc_vidvars.drawworld)
6556         {
6557                 // don't let sound skip if going slow
6558                 if (r_refdef.scene.extraupdate)
6559                         S_ExtraUpdate ();
6560
6561                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6562                 {
6563                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6564                         if (r_timereport_active)
6565                                 R_TimeReport("worldsky");
6566                 }
6567
6568                 if (R_DrawBrushModelsSky() && r_timereport_active)
6569                         R_TimeReport("bmodelsky");
6570
6571                 if (skyrendermasked && skyrenderlater)
6572                 {
6573                         // we have to force off the water clipping plane while rendering sky
6574                         R_SetupView(false);
6575                         R_Sky();
6576                         R_SetupView(true);
6577                         if (r_timereport_active)
6578                                 R_TimeReport("sky");
6579                 }
6580         }
6581
6582         R_AnimCache_CacheVisibleEntities();
6583         if (r_timereport_active)
6584                 R_TimeReport("animation");
6585
6586         R_Shadow_PrepareLights();
6587         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6588                 R_Shadow_PrepareModelShadows();
6589         if (r_timereport_active)
6590                 R_TimeReport("preparelights");
6591
6592         if (R_Shadow_ShadowMappingEnabled())
6593                 shadowmapping = true;
6594
6595         if (r_shadow_usingdeferredprepass)
6596                 R_Shadow_DrawPrepass();
6597
6598         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6599         {
6600                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6601                 if (r_timereport_active)
6602                         R_TimeReport("worlddepth");
6603         }
6604         if (r_depthfirst.integer >= 2)
6605         {
6606                 R_DrawModelsDepth();
6607                 if (r_timereport_active)
6608                         R_TimeReport("modeldepth");
6609         }
6610
6611         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6612         {
6613                 R_DrawModelShadowMaps();
6614                 R_ResetViewRendering3D();
6615                 // don't let sound skip if going slow
6616                 if (r_refdef.scene.extraupdate)
6617                         S_ExtraUpdate ();
6618         }
6619
6620         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6621         {
6622                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6623                 if (r_timereport_active)
6624                         R_TimeReport("world");
6625         }
6626
6627         // don't let sound skip if going slow
6628         if (r_refdef.scene.extraupdate)
6629                 S_ExtraUpdate ();
6630
6631         R_DrawModels();
6632         if (r_timereport_active)
6633                 R_TimeReport("models");
6634
6635         // don't let sound skip if going slow
6636         if (r_refdef.scene.extraupdate)
6637                 S_ExtraUpdate ();
6638
6639         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6640         {
6641                 R_DrawModelShadows();
6642                 R_ResetViewRendering3D();
6643                 // don't let sound skip if going slow
6644                 if (r_refdef.scene.extraupdate)
6645                         S_ExtraUpdate ();
6646         }
6647
6648         if (!r_shadow_usingdeferredprepass)
6649         {
6650                 R_Shadow_DrawLights();
6651                 if (r_timereport_active)
6652                         R_TimeReport("rtlights");
6653         }
6654
6655         // don't let sound skip if going slow
6656         if (r_refdef.scene.extraupdate)
6657                 S_ExtraUpdate ();
6658
6659         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6660         {
6661                 R_DrawModelShadows();
6662                 R_ResetViewRendering3D();
6663                 // don't let sound skip if going slow
6664                 if (r_refdef.scene.extraupdate)
6665                         S_ExtraUpdate ();
6666         }
6667
6668         if (cl.csqc_vidvars.drawworld)
6669         {
6670                 if (cl_decals_newsystem.integer)
6671                 {
6672                         R_DrawModelDecals();
6673                         if (r_timereport_active)
6674                                 R_TimeReport("modeldecals");
6675                 }
6676                 else
6677                 {
6678                         R_DrawDecals();
6679                         if (r_timereport_active)
6680                                 R_TimeReport("decals");
6681                 }
6682
6683                 R_DrawParticles();
6684                 if (r_timereport_active)
6685                         R_TimeReport("particles");
6686
6687                 R_DrawExplosions();
6688                 if (r_timereport_active)
6689                         R_TimeReport("explosions");
6690
6691                 R_DrawLightningBeams();
6692                 if (r_timereport_active)
6693                         R_TimeReport("lightning");
6694         }
6695
6696         VM_CL_AddPolygonsToMeshQueue();
6697
6698         if (r_refdef.view.showdebug)
6699         {
6700                 if (cl_locs_show.integer)
6701                 {
6702                         R_DrawLocs();
6703                         if (r_timereport_active)
6704                                 R_TimeReport("showlocs");
6705                 }
6706
6707                 if (r_drawportals.integer)
6708                 {
6709                         R_DrawPortals();
6710                         if (r_timereport_active)
6711                                 R_TimeReport("portals");
6712                 }
6713
6714                 if (r_showbboxes.value > 0)
6715                 {
6716                         R_DrawEntityBBoxes();
6717                         if (r_timereport_active)
6718                                 R_TimeReport("bboxes");
6719                 }
6720         }
6721
6722         R_MeshQueue_RenderTransparent();
6723         if (r_timereport_active)
6724                 R_TimeReport("drawtrans");
6725
6726         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))
6727         {
6728                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6729                 if (r_timereport_active)
6730                         R_TimeReport("worlddebug");
6731                 R_DrawModelsDebug();
6732                 if (r_timereport_active)
6733                         R_TimeReport("modeldebug");
6734         }
6735
6736         if (cl.csqc_vidvars.drawworld)
6737         {
6738                 R_Shadow_DrawCoronas();
6739                 if (r_timereport_active)
6740                         R_TimeReport("coronas");
6741         }
6742
6743 #if 0
6744         {
6745                 GL_DepthTest(false);
6746                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6747                 GL_Color(1, 1, 1, 1);
6748                 qglBegin(GL_POLYGON);
6749                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6750                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6751                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6752                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6753                 qglEnd();
6754                 qglBegin(GL_POLYGON);
6755                 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]);
6756                 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]);
6757                 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]);
6758                 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]);
6759                 qglEnd();
6760                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6761         }
6762 #endif
6763
6764         // don't let sound skip if going slow
6765         if (r_refdef.scene.extraupdate)
6766                 S_ExtraUpdate ();
6767
6768         R_ResetViewRendering2D();
6769 }
6770
6771 static const unsigned short bboxelements[36] =
6772 {
6773         5, 1, 3, 5, 3, 7,
6774         6, 2, 0, 6, 0, 4,
6775         7, 3, 2, 7, 2, 6,
6776         4, 0, 1, 4, 1, 5,
6777         4, 5, 7, 4, 7, 6,
6778         1, 0, 2, 1, 2, 3,
6779 };
6780
6781 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6782 {
6783         int i;
6784         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6785
6786         RSurf_ActiveWorldEntity();
6787
6788         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6789         GL_DepthMask(false);
6790         GL_DepthRange(0, 1);
6791         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6792 //      R_Mesh_ResetTextureState();
6793
6794         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6795         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6796         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6797         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6798         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6799         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6800         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6801         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6802         R_FillColors(color4f, 8, cr, cg, cb, ca);
6803         if (r_refdef.fogenabled)
6804         {
6805                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6806                 {
6807                         f1 = RSurf_FogVertex(v);
6808                         f2 = 1 - f1;
6809                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6810                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6811                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6812                 }
6813         }
6814         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6815         R_Mesh_ResetTextureState();
6816         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6817         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6818 }
6819
6820 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6821 {
6822         int i;
6823         float color[4];
6824         prvm_edict_t *edict;
6825         prvm_prog_t *prog_save = prog;
6826
6827         // this function draws bounding boxes of server entities
6828         if (!sv.active)
6829                 return;
6830
6831         GL_CullFace(GL_NONE);
6832         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6833
6834         prog = 0;
6835         SV_VM_Begin();
6836         for (i = 0;i < numsurfaces;i++)
6837         {
6838                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6839                 switch ((int)edict->fields.server->solid)
6840                 {
6841                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6842                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6843                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6844                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6845                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6846                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6847                 }
6848                 color[3] *= r_showbboxes.value;
6849                 color[3] = bound(0, color[3], 1);
6850                 GL_DepthTest(!r_showdisabledepthtest.integer);
6851                 GL_CullFace(r_refdef.view.cullface_front);
6852                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6853         }
6854         SV_VM_End();
6855         prog = prog_save;
6856 }
6857
6858 static void R_DrawEntityBBoxes(void)
6859 {
6860         int i;
6861         prvm_edict_t *edict;
6862         vec3_t center;
6863         prvm_prog_t *prog_save = prog;
6864
6865         // this function draws bounding boxes of server entities
6866         if (!sv.active)
6867                 return;
6868
6869         prog = 0;
6870         SV_VM_Begin();
6871         for (i = 0;i < prog->num_edicts;i++)
6872         {
6873                 edict = PRVM_EDICT_NUM(i);
6874                 if (edict->priv.server->free)
6875                         continue;
6876                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6877                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6878                         continue;
6879                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6880                         continue;
6881                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6882                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6883         }
6884         SV_VM_End();
6885         prog = prog_save;
6886 }
6887
6888 static const int nomodelelement3i[24] =
6889 {
6890         5, 2, 0,
6891         5, 1, 2,
6892         5, 0, 3,
6893         5, 3, 1,
6894         0, 2, 4,
6895         2, 1, 4,
6896         3, 0, 4,
6897         1, 3, 4
6898 };
6899
6900 static const unsigned short nomodelelement3s[24] =
6901 {
6902         5, 2, 0,
6903         5, 1, 2,
6904         5, 0, 3,
6905         5, 3, 1,
6906         0, 2, 4,
6907         2, 1, 4,
6908         3, 0, 4,
6909         1, 3, 4
6910 };
6911
6912 static const float nomodelvertex3f[6*3] =
6913 {
6914         -16,   0,   0,
6915          16,   0,   0,
6916           0, -16,   0,
6917           0,  16,   0,
6918           0,   0, -16,
6919           0,   0,  16
6920 };
6921
6922 static const float nomodelcolor4f[6*4] =
6923 {
6924         0.0f, 0.0f, 0.5f, 1.0f,
6925         0.0f, 0.0f, 0.5f, 1.0f,
6926         0.0f, 0.5f, 0.0f, 1.0f,
6927         0.0f, 0.5f, 0.0f, 1.0f,
6928         0.5f, 0.0f, 0.0f, 1.0f,
6929         0.5f, 0.0f, 0.0f, 1.0f
6930 };
6931
6932 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6933 {
6934         int i;
6935         float f1, f2, *c;
6936         float color4f[6*4];
6937
6938         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);
6939
6940         // this is only called once per entity so numsurfaces is always 1, and
6941         // surfacelist is always {0}, so this code does not handle batches
6942
6943         if (rsurface.ent_flags & RENDER_ADDITIVE)
6944         {
6945                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6946                 GL_DepthMask(false);
6947         }
6948         else if (rsurface.colormod[3] < 1)
6949         {
6950                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6951                 GL_DepthMask(false);
6952         }
6953         else
6954         {
6955                 GL_BlendFunc(GL_ONE, GL_ZERO);
6956                 GL_DepthMask(true);
6957         }
6958         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6959         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6960         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6961         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6962         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6963         for (i = 0, c = color4f;i < 6;i++, c += 4)
6964         {
6965                 c[0] *= rsurface.colormod[0];
6966                 c[1] *= rsurface.colormod[1];
6967                 c[2] *= rsurface.colormod[2];
6968                 c[3] *= rsurface.colormod[3];
6969         }
6970         if (r_refdef.fogenabled)
6971         {
6972                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6973                 {
6974                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6975                         f2 = 1 - f1;
6976                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6977                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6978                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6979                 }
6980         }
6981 //      R_Mesh_ResetTextureState();
6982         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6983         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6984         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6985 }
6986
6987 void R_DrawNoModel(entity_render_t *ent)
6988 {
6989         vec3_t org;
6990         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6991         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6992                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6993         else
6994                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6995 }
6996
6997 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6998 {
6999         vec3_t right1, right2, diff, normal;
7000
7001         VectorSubtract (org2, org1, normal);
7002
7003         // calculate 'right' vector for start
7004         VectorSubtract (r_refdef.view.origin, org1, diff);
7005         CrossProduct (normal, diff, right1);
7006         VectorNormalize (right1);
7007
7008         // calculate 'right' vector for end
7009         VectorSubtract (r_refdef.view.origin, org2, diff);
7010         CrossProduct (normal, diff, right2);
7011         VectorNormalize (right2);
7012
7013         vert[ 0] = org1[0] + width * right1[0];
7014         vert[ 1] = org1[1] + width * right1[1];
7015         vert[ 2] = org1[2] + width * right1[2];
7016         vert[ 3] = org1[0] - width * right1[0];
7017         vert[ 4] = org1[1] - width * right1[1];
7018         vert[ 5] = org1[2] - width * right1[2];
7019         vert[ 6] = org2[0] - width * right2[0];
7020         vert[ 7] = org2[1] - width * right2[1];
7021         vert[ 8] = org2[2] - width * right2[2];
7022         vert[ 9] = org2[0] + width * right2[0];
7023         vert[10] = org2[1] + width * right2[1];
7024         vert[11] = org2[2] + width * right2[2];
7025 }
7026
7027 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)
7028 {
7029         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7030         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7031         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7032         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7033         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7034         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7035         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7036         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7037         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7038         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7039         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7040         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7041 }
7042
7043 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7044 {
7045         int i;
7046         float *vertex3f;
7047         float v[3];
7048         VectorSet(v, x, y, z);
7049         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7050                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7051                         break;
7052         if (i == mesh->numvertices)
7053         {
7054                 if (mesh->numvertices < mesh->maxvertices)
7055                 {
7056                         VectorCopy(v, vertex3f);
7057                         mesh->numvertices++;
7058                 }
7059                 return mesh->numvertices;
7060         }
7061         else
7062                 return i;
7063 }
7064
7065 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7066 {
7067         int i;
7068         int *e, element[3];
7069         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7070         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7071         e = mesh->element3i + mesh->numtriangles * 3;
7072         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7073         {
7074                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7075                 if (mesh->numtriangles < mesh->maxtriangles)
7076                 {
7077                         *e++ = element[0];
7078                         *e++ = element[1];
7079                         *e++ = element[2];
7080                         mesh->numtriangles++;
7081                 }
7082                 element[1] = element[2];
7083         }
7084 }
7085
7086 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7087 {
7088         int i;
7089         int *e, element[3];
7090         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7091         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7092         e = mesh->element3i + mesh->numtriangles * 3;
7093         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7094         {
7095                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7096                 if (mesh->numtriangles < mesh->maxtriangles)
7097                 {
7098                         *e++ = element[0];
7099                         *e++ = element[1];
7100                         *e++ = element[2];
7101                         mesh->numtriangles++;
7102                 }
7103                 element[1] = element[2];
7104         }
7105 }
7106
7107 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7108 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7109 {
7110         int planenum, planenum2;
7111         int w;
7112         int tempnumpoints;
7113         mplane_t *plane, *plane2;
7114         double maxdist;
7115         double temppoints[2][256*3];
7116         // figure out how large a bounding box we need to properly compute this brush
7117         maxdist = 0;
7118         for (w = 0;w < numplanes;w++)
7119                 maxdist = max(maxdist, fabs(planes[w].dist));
7120         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7121         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7122         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7123         {
7124                 w = 0;
7125                 tempnumpoints = 4;
7126                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7127                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7128                 {
7129                         if (planenum2 == planenum)
7130                                 continue;
7131                         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);
7132                         w = !w;
7133                 }
7134                 if (tempnumpoints < 3)
7135                         continue;
7136                 // generate elements forming a triangle fan for this polygon
7137                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7138         }
7139 }
7140
7141 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)
7142 {
7143         texturelayer_t *layer;
7144         layer = t->currentlayers + t->currentnumlayers++;
7145         layer->type = type;
7146         layer->depthmask = depthmask;
7147         layer->blendfunc1 = blendfunc1;
7148         layer->blendfunc2 = blendfunc2;
7149         layer->texture = texture;
7150         layer->texmatrix = *matrix;
7151         layer->color[0] = r;
7152         layer->color[1] = g;
7153         layer->color[2] = b;
7154         layer->color[3] = a;
7155 }
7156
7157 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7158 {
7159         if(parms[0] == 0 && parms[1] == 0)
7160                 return false;
7161         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7162                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7163                         return false;
7164         return true;
7165 }
7166
7167 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7168 {
7169         double index, f;
7170         index = parms[2] + r_refdef.scene.time * parms[3];
7171         index -= floor(index);
7172         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7173         {
7174         default:
7175         case Q3WAVEFUNC_NONE:
7176         case Q3WAVEFUNC_NOISE:
7177         case Q3WAVEFUNC_COUNT:
7178                 f = 0;
7179                 break;
7180         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7181         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7182         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7183         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7184         case Q3WAVEFUNC_TRIANGLE:
7185                 index *= 4;
7186                 f = index - floor(index);
7187                 if (index < 1)
7188                         f = f;
7189                 else if (index < 2)
7190                         f = 1 - f;
7191                 else if (index < 3)
7192                         f = -f;
7193                 else
7194                         f = -(1 - f);
7195                 break;
7196         }
7197         f = parms[0] + parms[1] * f;
7198         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7199                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7200         return (float) f;
7201 }
7202
7203 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7204 {
7205         int w, h, idx;
7206         float f;
7207         float tcmat[12];
7208         matrix4x4_t matrix, temp;
7209         switch(tcmod->tcmod)
7210         {
7211                 case Q3TCMOD_COUNT:
7212                 case Q3TCMOD_NONE:
7213                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7214                                 matrix = r_waterscrollmatrix;
7215                         else
7216                                 matrix = identitymatrix;
7217                         break;
7218                 case Q3TCMOD_ENTITYTRANSLATE:
7219                         // this is used in Q3 to allow the gamecode to control texcoord
7220                         // scrolling on the entity, which is not supported in darkplaces yet.
7221                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7222                         break;
7223                 case Q3TCMOD_ROTATE:
7224                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7225                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7226                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7227                         break;
7228                 case Q3TCMOD_SCALE:
7229                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7230                         break;
7231                 case Q3TCMOD_SCROLL:
7232                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7233                         break;
7234                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7235                         w = (int) tcmod->parms[0];
7236                         h = (int) tcmod->parms[1];
7237                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7238                         f = f - floor(f);
7239                         idx = (int) floor(f * w * h);
7240                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7241                         break;
7242                 case Q3TCMOD_STRETCH:
7243                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7244                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7245                         break;
7246                 case Q3TCMOD_TRANSFORM:
7247                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7248                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7249                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7250                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7251                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7252                         break;
7253                 case Q3TCMOD_TURBULENT:
7254                         // this is handled in the RSurf_PrepareVertices function
7255                         matrix = identitymatrix;
7256                         break;
7257         }
7258         temp = *texmatrix;
7259         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7260 }
7261
7262 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7263 {
7264         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7265         char name[MAX_QPATH];
7266         skinframe_t *skinframe;
7267         unsigned char pixels[296*194];
7268         strlcpy(cache->name, skinname, sizeof(cache->name));
7269         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7270         if (developer_loading.integer)
7271                 Con_Printf("loading %s\n", name);
7272         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7273         if (!skinframe || !skinframe->base)
7274         {
7275                 unsigned char *f;
7276                 fs_offset_t filesize;
7277                 skinframe = NULL;
7278                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7279                 if (f)
7280                 {
7281                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7282                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7283                         Mem_Free(f);
7284                 }
7285         }
7286         cache->skinframe = skinframe;
7287 }
7288
7289 texture_t *R_GetCurrentTexture(texture_t *t)
7290 {
7291         int i;
7292         const entity_render_t *ent = rsurface.entity;
7293         dp_model_t *model = ent->model;
7294         q3shaderinfo_layer_tcmod_t *tcmod;
7295
7296         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7297                 return t->currentframe;
7298         t->update_lastrenderframe = r_textureframe;
7299         t->update_lastrenderentity = (void *)ent;
7300
7301         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7302                 t->camera_entity = ent->entitynumber;
7303         else
7304                 t->camera_entity = 0;
7305
7306         // switch to an alternate material if this is a q1bsp animated material
7307         {
7308                 texture_t *texture = t;
7309                 int s = rsurface.ent_skinnum;
7310                 if ((unsigned int)s >= (unsigned int)model->numskins)
7311                         s = 0;
7312                 if (model->skinscenes)
7313                 {
7314                         if (model->skinscenes[s].framecount > 1)
7315                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7316                         else
7317                                 s = model->skinscenes[s].firstframe;
7318                 }
7319                 if (s > 0)
7320                         t = t + s * model->num_surfaces;
7321                 if (t->animated)
7322                 {
7323                         // use an alternate animation if the entity's frame is not 0,
7324                         // and only if the texture has an alternate animation
7325                         if (rsurface.ent_alttextures && t->anim_total[1])
7326                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7327                         else
7328                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7329                 }
7330                 texture->currentframe = t;
7331         }
7332
7333         // update currentskinframe to be a qw skin or animation frame
7334         if (rsurface.ent_qwskin >= 0)
7335         {
7336                 i = rsurface.ent_qwskin;
7337                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7338                 {
7339                         r_qwskincache_size = cl.maxclients;
7340                         if (r_qwskincache)
7341                                 Mem_Free(r_qwskincache);
7342                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7343                 }
7344                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7345                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7346                 t->currentskinframe = r_qwskincache[i].skinframe;
7347                 if (t->currentskinframe == NULL)
7348                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7349         }
7350         else if (t->numskinframes >= 2)
7351                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7352         if (t->backgroundnumskinframes >= 2)
7353                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7354
7355         t->currentmaterialflags = t->basematerialflags;
7356         t->currentalpha = rsurface.colormod[3];
7357         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7358                 t->currentalpha *= r_wateralpha.value;
7359         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7360                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7361         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7362                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7363         if (!(rsurface.ent_flags & RENDER_LIGHT))
7364                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7365         else if (FAKELIGHT_ENABLED)
7366         {
7367                         // no modellight if using fakelight for the map
7368         }
7369         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7370         {
7371                 // pick a model lighting mode
7372                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7373                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7374                 else
7375                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7376         }
7377         if (rsurface.ent_flags & RENDER_ADDITIVE)
7378                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7379         else if (t->currentalpha < 1)
7380                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7381         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7382                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7383         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7384                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7385         if (t->backgroundnumskinframes)
7386                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7387         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7388         {
7389                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7390                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7391         }
7392         else
7393                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7394         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7395                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7396
7397         // there is no tcmod
7398         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7399         {
7400                 t->currenttexmatrix = r_waterscrollmatrix;
7401                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7402         }
7403         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7404         {
7405                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7406                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7407         }
7408
7409         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7410                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7411         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7412                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7413
7414         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7415         if (t->currentskinframe->qpixels)
7416                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7417         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7418         if (!t->basetexture)
7419                 t->basetexture = r_texture_notexture;
7420         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7421         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7422         t->nmaptexture = t->currentskinframe->nmap;
7423         if (!t->nmaptexture)
7424                 t->nmaptexture = r_texture_blanknormalmap;
7425         t->glosstexture = r_texture_black;
7426         t->glowtexture = t->currentskinframe->glow;
7427         t->fogtexture = t->currentskinframe->fog;
7428         t->reflectmasktexture = t->currentskinframe->reflect;
7429         if (t->backgroundnumskinframes)
7430         {
7431                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7432                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7433                 t->backgroundglosstexture = r_texture_black;
7434                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7435                 if (!t->backgroundnmaptexture)
7436                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7437         }
7438         else
7439         {
7440                 t->backgroundbasetexture = r_texture_white;
7441                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7442                 t->backgroundglosstexture = r_texture_black;
7443                 t->backgroundglowtexture = NULL;
7444         }
7445         t->specularpower = r_shadow_glossexponent.value;
7446         // TODO: store reference values for these in the texture?
7447         t->specularscale = 0;
7448         if (r_shadow_gloss.integer > 0)
7449         {
7450                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7451                 {
7452                         if (r_shadow_glossintensity.value > 0)
7453                         {
7454                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7455                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7456                                 t->specularscale = r_shadow_glossintensity.value;
7457                         }
7458                 }
7459                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7460                 {
7461                         t->glosstexture = r_texture_white;
7462                         t->backgroundglosstexture = r_texture_white;
7463                         t->specularscale = r_shadow_gloss2intensity.value;
7464                         t->specularpower = r_shadow_gloss2exponent.value;
7465                 }
7466         }
7467         t->specularscale *= t->specularscalemod;
7468         t->specularpower *= t->specularpowermod;
7469
7470         // lightmaps mode looks bad with dlights using actual texturing, so turn
7471         // off the colormap and glossmap, but leave the normalmap on as it still
7472         // accurately represents the shading involved
7473         if (gl_lightmaps.integer)
7474         {
7475                 t->basetexture = r_texture_grey128;
7476                 t->pantstexture = r_texture_black;
7477                 t->shirttexture = r_texture_black;
7478                 t->nmaptexture = r_texture_blanknormalmap;
7479                 t->glosstexture = r_texture_black;
7480                 t->glowtexture = NULL;
7481                 t->fogtexture = NULL;
7482                 t->reflectmasktexture = NULL;
7483                 t->backgroundbasetexture = NULL;
7484                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7485                 t->backgroundglosstexture = r_texture_black;
7486                 t->backgroundglowtexture = NULL;
7487                 t->specularscale = 0;
7488                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7489         }
7490
7491         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7492         VectorClear(t->dlightcolor);
7493         t->currentnumlayers = 0;
7494         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7495         {
7496                 int blendfunc1, blendfunc2;
7497                 qboolean depthmask;
7498                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7499                 {
7500                         blendfunc1 = GL_SRC_ALPHA;
7501                         blendfunc2 = GL_ONE;
7502                 }
7503                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7504                 {
7505                         blendfunc1 = GL_SRC_ALPHA;
7506                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7507                 }
7508                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7509                 {
7510                         blendfunc1 = t->customblendfunc[0];
7511                         blendfunc2 = t->customblendfunc[1];
7512                 }
7513                 else
7514                 {
7515                         blendfunc1 = GL_ONE;
7516                         blendfunc2 = GL_ZERO;
7517                 }
7518                 // don't colormod evilblend textures
7519                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
7520                         VectorSet(t->lightmapcolor, 1, 1, 1);
7521                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7522                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7523                 {
7524                         // fullbright is not affected by r_refdef.lightmapintensity
7525                         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]);
7526                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7527                                 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]);
7528                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7529                                 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]);
7530                 }
7531                 else
7532                 {
7533                         vec3_t ambientcolor;
7534                         float colorscale;
7535                         // set the color tint used for lights affecting this surface
7536                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7537                         colorscale = 2;
7538                         // q3bsp has no lightmap updates, so the lightstylevalue that
7539                         // would normally be baked into the lightmap must be
7540                         // applied to the color
7541                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7542                         if (model->type == mod_brushq3)
7543                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7544                         colorscale *= r_refdef.lightmapintensity;
7545                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7546                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7547                         // basic lit geometry
7548                         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]);
7549                         // add pants/shirt if needed
7550                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7551                                 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]);
7552                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7553                                 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]);
7554                         // now add ambient passes if needed
7555                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7556                         {
7557                                 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]);
7558                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7559                                         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]);
7560                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7561                                         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]);
7562                         }
7563                 }
7564                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7565                         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]);
7566                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7567                 {
7568                         // if this is opaque use alpha blend which will darken the earlier
7569                         // passes cheaply.
7570                         //
7571                         // if this is an alpha blended material, all the earlier passes
7572                         // were darkened by fog already, so we only need to add the fog
7573                         // color ontop through the fog mask texture
7574                         //
7575                         // if this is an additive blended material, all the earlier passes
7576                         // were darkened by fog already, and we should not add fog color
7577                         // (because the background was not darkened, there is no fog color
7578                         // that was lost behind it).
7579                         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]);
7580                 }
7581         }
7582
7583         return t->currentframe;
7584 }
7585
7586 rsurfacestate_t rsurface;
7587
7588 void RSurf_ActiveWorldEntity(void)
7589 {
7590         dp_model_t *model = r_refdef.scene.worldmodel;
7591         //if (rsurface.entity == r_refdef.scene.worldentity)
7592         //      return;
7593         rsurface.entity = r_refdef.scene.worldentity;
7594         rsurface.skeleton = NULL;
7595         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7596         rsurface.ent_skinnum = 0;
7597         rsurface.ent_qwskin = -1;
7598         rsurface.ent_shadertime = 0;
7599         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7600         rsurface.matrix = identitymatrix;
7601         rsurface.inversematrix = identitymatrix;
7602         rsurface.matrixscale = 1;
7603         rsurface.inversematrixscale = 1;
7604         R_EntityMatrix(&identitymatrix);
7605         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7606         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7607         rsurface.fograngerecip = r_refdef.fograngerecip;
7608         rsurface.fogheightfade = r_refdef.fogheightfade;
7609         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7610         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7611         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7612         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7613         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7614         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7615         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7616         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7617         rsurface.colormod[3] = 1;
7618         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);
7619         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7620         rsurface.frameblend[0].lerp = 1;
7621         rsurface.ent_alttextures = false;
7622         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7623         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7624         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7625         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7627         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7628         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7630         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7631         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7633         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7634         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7635         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7636         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7637         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7638         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7639         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7640         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7641         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7642         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7643         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7644         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7645         rsurface.modelelement3i = model->surfmesh.data_element3i;
7646         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7647         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7648         rsurface.modelelement3s = model->surfmesh.data_element3s;
7649         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7650         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7651         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7652         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7653         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7654         rsurface.modelsurfaces = model->data_surfaces;
7655         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7656         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7657         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7658         rsurface.modelgeneratedvertex = false;
7659         rsurface.batchgeneratedvertex = false;
7660         rsurface.batchfirstvertex = 0;
7661         rsurface.batchnumvertices = 0;
7662         rsurface.batchfirsttriangle = 0;
7663         rsurface.batchnumtriangles = 0;
7664         rsurface.batchvertex3f  = NULL;
7665         rsurface.batchvertex3f_vertexbuffer = NULL;
7666         rsurface.batchvertex3f_bufferoffset = 0;
7667         rsurface.batchsvector3f = NULL;
7668         rsurface.batchsvector3f_vertexbuffer = NULL;
7669         rsurface.batchsvector3f_bufferoffset = 0;
7670         rsurface.batchtvector3f = NULL;
7671         rsurface.batchtvector3f_vertexbuffer = NULL;
7672         rsurface.batchtvector3f_bufferoffset = 0;
7673         rsurface.batchnormal3f  = NULL;
7674         rsurface.batchnormal3f_vertexbuffer = NULL;
7675         rsurface.batchnormal3f_bufferoffset = 0;
7676         rsurface.batchlightmapcolor4f = NULL;
7677         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7678         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7679         rsurface.batchtexcoordtexture2f = NULL;
7680         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7681         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7682         rsurface.batchtexcoordlightmap2f = NULL;
7683         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7684         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7685         rsurface.batchvertexmesh = NULL;
7686         rsurface.batchvertexmeshbuffer = NULL;
7687         rsurface.batchvertex3fbuffer = NULL;
7688         rsurface.batchelement3i = NULL;
7689         rsurface.batchelement3i_indexbuffer = NULL;
7690         rsurface.batchelement3i_bufferoffset = 0;
7691         rsurface.batchelement3s = NULL;
7692         rsurface.batchelement3s_indexbuffer = NULL;
7693         rsurface.batchelement3s_bufferoffset = 0;
7694         rsurface.passcolor4f = NULL;
7695         rsurface.passcolor4f_vertexbuffer = NULL;
7696         rsurface.passcolor4f_bufferoffset = 0;
7697 }
7698
7699 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7700 {
7701         dp_model_t *model = ent->model;
7702         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7703         //      return;
7704         rsurface.entity = (entity_render_t *)ent;
7705         rsurface.skeleton = ent->skeleton;
7706         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7707         rsurface.ent_skinnum = ent->skinnum;
7708         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;
7709         rsurface.ent_shadertime = ent->shadertime;
7710         rsurface.ent_flags = ent->flags;
7711         rsurface.matrix = ent->matrix;
7712         rsurface.inversematrix = ent->inversematrix;
7713         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7714         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7715         R_EntityMatrix(&rsurface.matrix);
7716         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7717         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7718         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7719         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7720         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7721         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7722         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7723         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7724         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7725         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7726         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7727         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7728         rsurface.colormod[3] = ent->alpha;
7729         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7730         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7731         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7732         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7733         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7734         if (ent->model->brush.submodel && !prepass)
7735         {
7736                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7737                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7738         }
7739         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7740         {
7741                 if (ent->animcache_vertex3f)
7742                 {
7743                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7744                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7745                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7746                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7747                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7748                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7749                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7750                 }
7751                 else if (wanttangents)
7752                 {
7753                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7754                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7755                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7756                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7757                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7758                         rsurface.modelvertexmesh = NULL;
7759                         rsurface.modelvertexmeshbuffer = NULL;
7760                         rsurface.modelvertex3fbuffer = NULL;
7761                 }
7762                 else if (wantnormals)
7763                 {
7764                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7765                         rsurface.modelsvector3f = NULL;
7766                         rsurface.modeltvector3f = NULL;
7767                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7768                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7769                         rsurface.modelvertexmesh = NULL;
7770                         rsurface.modelvertexmeshbuffer = NULL;
7771                         rsurface.modelvertex3fbuffer = NULL;
7772                 }
7773                 else
7774                 {
7775                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7776                         rsurface.modelsvector3f = NULL;
7777                         rsurface.modeltvector3f = NULL;
7778                         rsurface.modelnormal3f = NULL;
7779                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7780                         rsurface.modelvertexmesh = NULL;
7781                         rsurface.modelvertexmeshbuffer = NULL;
7782                         rsurface.modelvertex3fbuffer = NULL;
7783                 }
7784                 rsurface.modelvertex3f_vertexbuffer = 0;
7785                 rsurface.modelvertex3f_bufferoffset = 0;
7786                 rsurface.modelsvector3f_vertexbuffer = 0;
7787                 rsurface.modelsvector3f_bufferoffset = 0;
7788                 rsurface.modeltvector3f_vertexbuffer = 0;
7789                 rsurface.modeltvector3f_bufferoffset = 0;
7790                 rsurface.modelnormal3f_vertexbuffer = 0;
7791                 rsurface.modelnormal3f_bufferoffset = 0;
7792                 rsurface.modelgeneratedvertex = true;
7793         }
7794         else
7795         {
7796                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7797                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7799                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7800                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7802                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7803                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7805                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7806                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7807                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7808                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7809                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7810                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7811                 rsurface.modelgeneratedvertex = false;
7812         }
7813         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7814         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7815         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7816         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7817         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7818         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7819         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7820         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7821         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7822         rsurface.modelelement3i = model->surfmesh.data_element3i;
7823         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7824         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7825         rsurface.modelelement3s = model->surfmesh.data_element3s;
7826         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7827         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7828         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7829         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7830         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7831         rsurface.modelsurfaces = model->data_surfaces;
7832         rsurface.batchgeneratedvertex = false;
7833         rsurface.batchfirstvertex = 0;
7834         rsurface.batchnumvertices = 0;
7835         rsurface.batchfirsttriangle = 0;
7836         rsurface.batchnumtriangles = 0;
7837         rsurface.batchvertex3f  = NULL;
7838         rsurface.batchvertex3f_vertexbuffer = NULL;
7839         rsurface.batchvertex3f_bufferoffset = 0;
7840         rsurface.batchsvector3f = NULL;
7841         rsurface.batchsvector3f_vertexbuffer = NULL;
7842         rsurface.batchsvector3f_bufferoffset = 0;
7843         rsurface.batchtvector3f = NULL;
7844         rsurface.batchtvector3f_vertexbuffer = NULL;
7845         rsurface.batchtvector3f_bufferoffset = 0;
7846         rsurface.batchnormal3f  = NULL;
7847         rsurface.batchnormal3f_vertexbuffer = NULL;
7848         rsurface.batchnormal3f_bufferoffset = 0;
7849         rsurface.batchlightmapcolor4f = NULL;
7850         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7851         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7852         rsurface.batchtexcoordtexture2f = NULL;
7853         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7854         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7855         rsurface.batchtexcoordlightmap2f = NULL;
7856         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7857         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7858         rsurface.batchvertexmesh = NULL;
7859         rsurface.batchvertexmeshbuffer = NULL;
7860         rsurface.batchvertex3fbuffer = NULL;
7861         rsurface.batchelement3i = NULL;
7862         rsurface.batchelement3i_indexbuffer = NULL;
7863         rsurface.batchelement3i_bufferoffset = 0;
7864         rsurface.batchelement3s = NULL;
7865         rsurface.batchelement3s_indexbuffer = NULL;
7866         rsurface.batchelement3s_bufferoffset = 0;
7867         rsurface.passcolor4f = NULL;
7868         rsurface.passcolor4f_vertexbuffer = NULL;
7869         rsurface.passcolor4f_bufferoffset = 0;
7870 }
7871
7872 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)
7873 {
7874         rsurface.entity = r_refdef.scene.worldentity;
7875         rsurface.skeleton = NULL;
7876         rsurface.ent_skinnum = 0;
7877         rsurface.ent_qwskin = -1;
7878         rsurface.ent_shadertime = shadertime;
7879         rsurface.ent_flags = entflags;
7880         rsurface.modelnumvertices = numvertices;
7881         rsurface.modelnumtriangles = numtriangles;
7882         rsurface.matrix = *matrix;
7883         rsurface.inversematrix = *inversematrix;
7884         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7885         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7886         R_EntityMatrix(&rsurface.matrix);
7887         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7888         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7889         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7890         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7891         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7892         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7893         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7894         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7895         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7896         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7897         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7898         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7899         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);
7900         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7901         rsurface.frameblend[0].lerp = 1;
7902         rsurface.ent_alttextures = false;
7903         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7904         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7905         if (wanttangents)
7906         {
7907                 rsurface.modelvertex3f = (float *)vertex3f;
7908                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7909                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7910                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7911         }
7912         else if (wantnormals)
7913         {
7914                 rsurface.modelvertex3f = (float *)vertex3f;
7915                 rsurface.modelsvector3f = NULL;
7916                 rsurface.modeltvector3f = NULL;
7917                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7918         }
7919         else
7920         {
7921                 rsurface.modelvertex3f = (float *)vertex3f;
7922                 rsurface.modelsvector3f = NULL;
7923                 rsurface.modeltvector3f = NULL;
7924                 rsurface.modelnormal3f = NULL;
7925         }
7926         rsurface.modelvertexmesh = NULL;
7927         rsurface.modelvertexmeshbuffer = NULL;
7928         rsurface.modelvertex3fbuffer = NULL;
7929         rsurface.modelvertex3f_vertexbuffer = 0;
7930         rsurface.modelvertex3f_bufferoffset = 0;
7931         rsurface.modelsvector3f_vertexbuffer = 0;
7932         rsurface.modelsvector3f_bufferoffset = 0;
7933         rsurface.modeltvector3f_vertexbuffer = 0;
7934         rsurface.modeltvector3f_bufferoffset = 0;
7935         rsurface.modelnormal3f_vertexbuffer = 0;
7936         rsurface.modelnormal3f_bufferoffset = 0;
7937         rsurface.modelgeneratedvertex = true;
7938         rsurface.modellightmapcolor4f  = (float *)color4f;
7939         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7940         rsurface.modellightmapcolor4f_bufferoffset = 0;
7941         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7942         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7943         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7944         rsurface.modeltexcoordlightmap2f  = NULL;
7945         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7946         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7947         rsurface.modelelement3i = (int *)element3i;
7948         rsurface.modelelement3i_indexbuffer = NULL;
7949         rsurface.modelelement3i_bufferoffset = 0;
7950         rsurface.modelelement3s = (unsigned short *)element3s;
7951         rsurface.modelelement3s_indexbuffer = NULL;
7952         rsurface.modelelement3s_bufferoffset = 0;
7953         rsurface.modellightmapoffsets = NULL;
7954         rsurface.modelsurfaces = NULL;
7955         rsurface.batchgeneratedvertex = false;
7956         rsurface.batchfirstvertex = 0;
7957         rsurface.batchnumvertices = 0;
7958         rsurface.batchfirsttriangle = 0;
7959         rsurface.batchnumtriangles = 0;
7960         rsurface.batchvertex3f  = NULL;
7961         rsurface.batchvertex3f_vertexbuffer = NULL;
7962         rsurface.batchvertex3f_bufferoffset = 0;
7963         rsurface.batchsvector3f = NULL;
7964         rsurface.batchsvector3f_vertexbuffer = NULL;
7965         rsurface.batchsvector3f_bufferoffset = 0;
7966         rsurface.batchtvector3f = NULL;
7967         rsurface.batchtvector3f_vertexbuffer = NULL;
7968         rsurface.batchtvector3f_bufferoffset = 0;
7969         rsurface.batchnormal3f  = NULL;
7970         rsurface.batchnormal3f_vertexbuffer = NULL;
7971         rsurface.batchnormal3f_bufferoffset = 0;
7972         rsurface.batchlightmapcolor4f = NULL;
7973         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7974         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7975         rsurface.batchtexcoordtexture2f = NULL;
7976         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7977         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7978         rsurface.batchtexcoordlightmap2f = NULL;
7979         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7980         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7981         rsurface.batchvertexmesh = NULL;
7982         rsurface.batchvertexmeshbuffer = NULL;
7983         rsurface.batchvertex3fbuffer = NULL;
7984         rsurface.batchelement3i = NULL;
7985         rsurface.batchelement3i_indexbuffer = NULL;
7986         rsurface.batchelement3i_bufferoffset = 0;
7987         rsurface.batchelement3s = NULL;
7988         rsurface.batchelement3s_indexbuffer = NULL;
7989         rsurface.batchelement3s_bufferoffset = 0;
7990         rsurface.passcolor4f = NULL;
7991         rsurface.passcolor4f_vertexbuffer = NULL;
7992         rsurface.passcolor4f_bufferoffset = 0;
7993
7994         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7995         {
7996                 if ((wantnormals || wanttangents) && !normal3f)
7997                 {
7998                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7999                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8000                 }
8001                 if (wanttangents && !svector3f)
8002                 {
8003                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8004                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8005                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8006                 }
8007         }
8008 }
8009
8010 float RSurf_FogPoint(const float *v)
8011 {
8012         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8013         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8014         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8015         float FogHeightFade = r_refdef.fogheightfade;
8016         float fogfrac;
8017         unsigned int fogmasktableindex;
8018         if (r_refdef.fogplaneviewabove)
8019                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8020         else
8021                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8022         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8023         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8024 }
8025
8026 float RSurf_FogVertex(const float *v)
8027 {
8028         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8029         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8030         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8031         float FogHeightFade = rsurface.fogheightfade;
8032         float fogfrac;
8033         unsigned int fogmasktableindex;
8034         if (r_refdef.fogplaneviewabove)
8035                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8036         else
8037                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8038         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8039         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8040 }
8041
8042 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8043 {
8044         int i;
8045         for (i = 0;i < numelements;i++)
8046                 outelement3i[i] = inelement3i[i] + adjust;
8047 }
8048
8049 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8050 extern cvar_t gl_vbo;
8051 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8052 {
8053         int deformindex;
8054         int firsttriangle;
8055         int numtriangles;
8056         int firstvertex;
8057         int endvertex;
8058         int numvertices;
8059         int surfacefirsttriangle;
8060         int surfacenumtriangles;
8061         int surfacefirstvertex;
8062         int surfaceendvertex;
8063         int surfacenumvertices;
8064         int batchnumvertices;
8065         int batchnumtriangles;
8066         int needsupdate;
8067         int i, j;
8068         qboolean gaps;
8069         qboolean dynamicvertex;
8070         float amplitude;
8071         float animpos;
8072         float scale;
8073         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8074         float waveparms[4];
8075         q3shaderinfo_deform_t *deform;
8076         const msurface_t *surface, *firstsurface;
8077         r_vertexmesh_t *vertexmesh;
8078         if (!texturenumsurfaces)
8079                 return;
8080         // find vertex range of this surface batch
8081         gaps = false;
8082         firstsurface = texturesurfacelist[0];
8083         firsttriangle = firstsurface->num_firsttriangle;
8084         batchnumvertices = 0;
8085         batchnumtriangles = 0;
8086         firstvertex = endvertex = firstsurface->num_firstvertex;
8087         for (i = 0;i < texturenumsurfaces;i++)
8088         {
8089                 surface = texturesurfacelist[i];
8090                 if (surface != firstsurface + i)
8091                         gaps = true;
8092                 surfacefirstvertex = surface->num_firstvertex;
8093                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8094                 surfacenumvertices = surface->num_vertices;
8095                 surfacenumtriangles = surface->num_triangles;
8096                 if (firstvertex > surfacefirstvertex)
8097                         firstvertex = surfacefirstvertex;
8098                 if (endvertex < surfaceendvertex)
8099                         endvertex = surfaceendvertex;
8100                 batchnumvertices += surfacenumvertices;
8101                 batchnumtriangles += surfacenumtriangles;
8102         }
8103
8104         // we now know the vertex range used, and if there are any gaps in it
8105         rsurface.batchfirstvertex = firstvertex;
8106         rsurface.batchnumvertices = endvertex - firstvertex;
8107         rsurface.batchfirsttriangle = firsttriangle;
8108         rsurface.batchnumtriangles = batchnumtriangles;
8109
8110         // this variable holds flags for which properties have been updated that
8111         // may require regenerating vertexmesh array...
8112         needsupdate = 0;
8113
8114         // check if any dynamic vertex processing must occur
8115         dynamicvertex = false;
8116
8117         // if there is a chance of animated vertex colors, it's a dynamic batch
8118         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8119         {
8120                 dynamicvertex = true;
8121                 batchneed |= BATCHNEED_NOGAPS;
8122                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8123         }
8124
8125         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8126         {
8127                 switch (deform->deform)
8128                 {
8129                 default:
8130                 case Q3DEFORM_PROJECTIONSHADOW:
8131                 case Q3DEFORM_TEXT0:
8132                 case Q3DEFORM_TEXT1:
8133                 case Q3DEFORM_TEXT2:
8134                 case Q3DEFORM_TEXT3:
8135                 case Q3DEFORM_TEXT4:
8136                 case Q3DEFORM_TEXT5:
8137                 case Q3DEFORM_TEXT6:
8138                 case Q3DEFORM_TEXT7:
8139                 case Q3DEFORM_NONE:
8140                         break;
8141                 case Q3DEFORM_AUTOSPRITE:
8142                         dynamicvertex = true;
8143                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8144                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8145                         break;
8146                 case Q3DEFORM_AUTOSPRITE2:
8147                         dynamicvertex = true;
8148                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8149                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8150                         break;
8151                 case Q3DEFORM_NORMAL:
8152                         dynamicvertex = true;
8153                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8154                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8155                         break;
8156                 case Q3DEFORM_WAVE:
8157                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8158                                 break; // if wavefunc is a nop, ignore this transform
8159                         dynamicvertex = true;
8160                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8161                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8162                         break;
8163                 case Q3DEFORM_BULGE:
8164                         dynamicvertex = true;
8165                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8166                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8167                         break;
8168                 case Q3DEFORM_MOVE:
8169                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8170                                 break; // if wavefunc is a nop, ignore this transform
8171                         dynamicvertex = true;
8172                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8173                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8174                         break;
8175                 }
8176         }
8177         switch(rsurface.texture->tcgen.tcgen)
8178         {
8179         default:
8180         case Q3TCGEN_TEXTURE:
8181                 break;
8182         case Q3TCGEN_LIGHTMAP:
8183                 dynamicvertex = true;
8184                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8185                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8186                 break;
8187         case Q3TCGEN_VECTOR:
8188                 dynamicvertex = true;
8189                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8190                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8191                 break;
8192         case Q3TCGEN_ENVIRONMENT:
8193                 dynamicvertex = true;
8194                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8195                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8196                 break;
8197         }
8198         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8199         {
8200                 dynamicvertex = true;
8201                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8202                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8203         }
8204
8205         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8206         {
8207                 dynamicvertex = true;
8208                 batchneed |= BATCHNEED_NOGAPS;
8209                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8210         }
8211
8212         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8213         {
8214                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8215                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8216                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8217                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8218                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8219                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8220                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8221         }
8222
8223         // when the model data has no vertex buffer (dynamic mesh), we need to
8224         // eliminate gaps
8225         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8226                 batchneed |= BATCHNEED_NOGAPS;
8227
8228         // if needsupdate, we have to do a dynamic vertex batch for sure
8229         if (needsupdate & batchneed)
8230                 dynamicvertex = true;
8231
8232         // see if we need to build vertexmesh from arrays
8233         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8234                 dynamicvertex = true;
8235
8236         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8237         // also some drivers strongly dislike firstvertex
8238         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8239                 dynamicvertex = true;
8240
8241         rsurface.batchvertex3f = rsurface.modelvertex3f;
8242         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8243         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8244         rsurface.batchsvector3f = rsurface.modelsvector3f;
8245         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8246         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8247         rsurface.batchtvector3f = rsurface.modeltvector3f;
8248         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8249         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8250         rsurface.batchnormal3f = rsurface.modelnormal3f;
8251         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8252         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8253         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8254         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8255         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8256         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8257         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8258         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8259         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8260         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8261         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8262         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8263         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8264         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8265         rsurface.batchelement3i = rsurface.modelelement3i;
8266         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8267         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8268         rsurface.batchelement3s = rsurface.modelelement3s;
8269         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8270         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8271
8272         // if any dynamic vertex processing has to occur in software, we copy the
8273         // entire surface list together before processing to rebase the vertices
8274         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8275         //
8276         // if any gaps exist and we do not have a static vertex buffer, we have to
8277         // copy the surface list together to avoid wasting upload bandwidth on the
8278         // vertices in the gaps.
8279         //
8280         // if gaps exist and we have a static vertex buffer, we still have to
8281         // combine the index buffer ranges into one dynamic index buffer.
8282         //
8283         // in all cases we end up with data that can be drawn in one call.
8284
8285         if (!dynamicvertex)
8286         {
8287                 // static vertex data, just set pointers...
8288                 rsurface.batchgeneratedvertex = false;
8289                 // if there are gaps, we want to build a combined index buffer,
8290                 // otherwise use the original static buffer with an appropriate offset
8291                 if (gaps)
8292                 {
8293                         // build a new triangle elements array for this batch
8294                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8295                         rsurface.batchfirsttriangle = 0;
8296                         numtriangles = 0;
8297                         for (i = 0;i < texturenumsurfaces;i++)
8298                         {
8299                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8300                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8301                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8302                                 numtriangles += surfacenumtriangles;
8303                         }
8304                         rsurface.batchelement3i_indexbuffer = NULL;
8305                         rsurface.batchelement3i_bufferoffset = 0;
8306                         rsurface.batchelement3s = NULL;
8307                         rsurface.batchelement3s_indexbuffer = NULL;
8308                         rsurface.batchelement3s_bufferoffset = 0;
8309                         if (endvertex <= 65536)
8310                         {
8311                                 // make a 16bit (unsigned short) index array if possible
8312                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8313                                 for (i = 0;i < numtriangles*3;i++)
8314                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8315                         }
8316                 }
8317                 return;
8318         }
8319
8320         // something needs software processing, do it for real...
8321         // we only directly handle separate array data in this case and then
8322         // generate interleaved data if needed...
8323         rsurface.batchgeneratedvertex = true;
8324
8325         // now copy the vertex data into a combined array and make an index array
8326         // (this is what Quake3 does all the time)
8327         //if (gaps || rsurface.batchfirstvertex)
8328         {
8329                 rsurface.batchvertex3fbuffer = NULL;
8330                 rsurface.batchvertexmesh = NULL;
8331                 rsurface.batchvertexmeshbuffer = NULL;
8332                 rsurface.batchvertex3f = NULL;
8333                 rsurface.batchvertex3f_vertexbuffer = NULL;
8334                 rsurface.batchvertex3f_bufferoffset = 0;
8335                 rsurface.batchsvector3f = NULL;
8336                 rsurface.batchsvector3f_vertexbuffer = NULL;
8337                 rsurface.batchsvector3f_bufferoffset = 0;
8338                 rsurface.batchtvector3f = NULL;
8339                 rsurface.batchtvector3f_vertexbuffer = NULL;
8340                 rsurface.batchtvector3f_bufferoffset = 0;
8341                 rsurface.batchnormal3f = NULL;
8342                 rsurface.batchnormal3f_vertexbuffer = NULL;
8343                 rsurface.batchnormal3f_bufferoffset = 0;
8344                 rsurface.batchlightmapcolor4f = NULL;
8345                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8346                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8347                 rsurface.batchtexcoordtexture2f = NULL;
8348                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8349                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8350                 rsurface.batchtexcoordlightmap2f = NULL;
8351                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8352                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8353                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8354                 rsurface.batchelement3i_indexbuffer = NULL;
8355                 rsurface.batchelement3i_bufferoffset = 0;
8356                 rsurface.batchelement3s = NULL;
8357                 rsurface.batchelement3s_indexbuffer = NULL;
8358                 rsurface.batchelement3s_bufferoffset = 0;
8359                 // we'll only be setting up certain arrays as needed
8360                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8361                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8362                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8363                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8364                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8365                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8366                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8367                 {
8368                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8369                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8370                 }
8371                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8372                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8373                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8374                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8375                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8376                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8377                 numvertices = 0;
8378                 numtriangles = 0;
8379                 for (i = 0;i < texturenumsurfaces;i++)
8380                 {
8381                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8382                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8383                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8384                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8385                         // copy only the data requested
8386                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8387                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8388                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8389                         {
8390                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8391                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8392                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8393                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8394                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8395                                 {
8396                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8397                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8398                                 }
8399                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8400                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8401                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8402                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8403                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8404                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8405                         }
8406                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8407                         numvertices += surfacenumvertices;
8408                         numtriangles += surfacenumtriangles;
8409                 }
8410
8411                 // generate a 16bit index array as well if possible
8412                 // (in general, dynamic batches fit)
8413                 if (numvertices <= 65536)
8414                 {
8415                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8416                         for (i = 0;i < numtriangles*3;i++)
8417                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8418                 }
8419
8420                 // since we've copied everything, the batch now starts at 0
8421                 rsurface.batchfirstvertex = 0;
8422                 rsurface.batchnumvertices = batchnumvertices;
8423                 rsurface.batchfirsttriangle = 0;
8424                 rsurface.batchnumtriangles = batchnumtriangles;
8425         }
8426
8427         // q1bsp surfaces rendered in vertex color mode have to have colors
8428         // calculated based on lightstyles
8429         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8430         {
8431                 // generate color arrays for the surfaces in this list
8432                 int c[4];
8433                 int scale;
8434                 int size3;
8435                 const int *offsets;
8436                 const unsigned char *lm;
8437                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8438                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8439                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8440                 numvertices = 0;
8441                 for (i = 0;i < texturenumsurfaces;i++)
8442                 {
8443                         surface = texturesurfacelist[i];
8444                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8445                         surfacenumvertices = surface->num_vertices;
8446                         if (surface->lightmapinfo->samples)
8447                         {
8448                                 for (j = 0;j < surfacenumvertices;j++)
8449                                 {
8450                                         lm = surface->lightmapinfo->samples + offsets[j];
8451                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8452                                         VectorScale(lm, scale, c);
8453                                         if (surface->lightmapinfo->styles[1] != 255)
8454                                         {
8455                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8456                                                 lm += size3;
8457                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8458                                                 VectorMA(c, scale, lm, c);
8459                                                 if (surface->lightmapinfo->styles[2] != 255)
8460                                                 {
8461                                                         lm += size3;
8462                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8463                                                         VectorMA(c, scale, lm, c);
8464                                                         if (surface->lightmapinfo->styles[3] != 255)
8465                                                         {
8466                                                                 lm += size3;
8467                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8468                                                                 VectorMA(c, scale, lm, c);
8469                                                         }
8470                                                 }
8471                                         }
8472                                         c[0] >>= 7;
8473                                         c[1] >>= 7;
8474                                         c[2] >>= 7;
8475                                         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);
8476                                         numvertices++;
8477                                 }
8478                         }
8479                         else
8480                         {
8481                                 for (j = 0;j < surfacenumvertices;j++)
8482                                 {
8483                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8484                                         numvertices++;
8485                                 }
8486                         }
8487                 }
8488         }
8489
8490         // if vertices are deformed (sprite flares and things in maps, possibly
8491         // water waves, bulges and other deformations), modify the copied vertices
8492         // in place
8493         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8494         {
8495                 switch (deform->deform)
8496                 {
8497                 default:
8498                 case Q3DEFORM_PROJECTIONSHADOW:
8499                 case Q3DEFORM_TEXT0:
8500                 case Q3DEFORM_TEXT1:
8501                 case Q3DEFORM_TEXT2:
8502                 case Q3DEFORM_TEXT3:
8503                 case Q3DEFORM_TEXT4:
8504                 case Q3DEFORM_TEXT5:
8505                 case Q3DEFORM_TEXT6:
8506                 case Q3DEFORM_TEXT7:
8507                 case Q3DEFORM_NONE:
8508                         break;
8509                 case Q3DEFORM_AUTOSPRITE:
8510                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8511                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8512                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8513                         VectorNormalize(newforward);
8514                         VectorNormalize(newright);
8515                         VectorNormalize(newup);
8516 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8517 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8518 //                      rsurface.batchvertex3f_bufferoffset = 0;
8519 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8520 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8521 //                      rsurface.batchsvector3f_bufferoffset = 0;
8522 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8523 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8524 //                      rsurface.batchtvector3f_bufferoffset = 0;
8525 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8526 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8527 //                      rsurface.batchnormal3f_bufferoffset = 0;
8528                         // a single autosprite surface can contain multiple sprites...
8529                         for (j = 0;j < batchnumvertices - 3;j += 4)
8530                         {
8531                                 VectorClear(center);
8532                                 for (i = 0;i < 4;i++)
8533                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8534                                 VectorScale(center, 0.25f, center);
8535                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8536                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8537                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8538                                 for (i = 0;i < 4;i++)
8539                                 {
8540                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8541                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8542                                 }
8543                         }
8544                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8545                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8546                         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);
8547                         break;
8548                 case Q3DEFORM_AUTOSPRITE2:
8549                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8550                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8551                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8552                         VectorNormalize(newforward);
8553                         VectorNormalize(newright);
8554                         VectorNormalize(newup);
8555 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8556 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8557 //                      rsurface.batchvertex3f_bufferoffset = 0;
8558                         {
8559                                 const float *v1, *v2;
8560                                 vec3_t start, end;
8561                                 float f, l;
8562                                 struct
8563                                 {
8564                                         float length2;
8565                                         const float *v1;
8566                                         const float *v2;
8567                                 }
8568                                 shortest[2];
8569                                 memset(shortest, 0, sizeof(shortest));
8570                                 // a single autosprite surface can contain multiple sprites...
8571                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8572                                 {
8573                                         VectorClear(center);
8574                                         for (i = 0;i < 4;i++)
8575                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8576                                         VectorScale(center, 0.25f, center);
8577                                         // find the two shortest edges, then use them to define the
8578                                         // axis vectors for rotating around the central axis
8579                                         for (i = 0;i < 6;i++)
8580                                         {
8581                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8582                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8583                                                 l = VectorDistance2(v1, v2);
8584                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8585                                                 if (v1[2] != v2[2])
8586                                                         l += (1.0f / 1024.0f);
8587                                                 if (shortest[0].length2 > l || i == 0)
8588                                                 {
8589                                                         shortest[1] = shortest[0];
8590                                                         shortest[0].length2 = l;
8591                                                         shortest[0].v1 = v1;
8592                                                         shortest[0].v2 = v2;
8593                                                 }
8594                                                 else if (shortest[1].length2 > l || i == 1)
8595                                                 {
8596                                                         shortest[1].length2 = l;
8597                                                         shortest[1].v1 = v1;
8598                                                         shortest[1].v2 = v2;
8599                                                 }
8600                                         }
8601                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8602                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8603                                         // this calculates the right vector from the shortest edge
8604                                         // and the up vector from the edge midpoints
8605                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8606                                         VectorNormalize(right);
8607                                         VectorSubtract(end, start, up);
8608                                         VectorNormalize(up);
8609                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8610                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8611                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8612                                         VectorNegate(forward, forward);
8613                                         VectorReflect(forward, 0, up, forward);
8614                                         VectorNormalize(forward);
8615                                         CrossProduct(up, forward, newright);
8616                                         VectorNormalize(newright);
8617                                         // rotate the quad around the up axis vector, this is made
8618                                         // especially easy by the fact we know the quad is flat,
8619                                         // so we only have to subtract the center position and
8620                                         // measure distance along the right vector, and then
8621                                         // multiply that by the newright vector and add back the
8622                                         // center position
8623                                         // we also need to subtract the old position to undo the
8624                                         // displacement from the center, which we do with a
8625                                         // DotProduct, the subtraction/addition of center is also
8626                                         // optimized into DotProducts here
8627                                         l = DotProduct(right, center);
8628                                         for (i = 0;i < 4;i++)
8629                                         {
8630                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8631                                                 f = DotProduct(right, v1) - l;
8632                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8633                                         }
8634                                 }
8635                         }
8636                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8637                         {
8638 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8639 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8640 //                              rsurface.batchnormal3f_bufferoffset = 0;
8641                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8642                         }
8643                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8644                         {
8645 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8646 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8647 //                              rsurface.batchsvector3f_bufferoffset = 0;
8648 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8649 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8650 //                              rsurface.batchtvector3f_bufferoffset = 0;
8651                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8652                         }
8653                         break;
8654                 case Q3DEFORM_NORMAL:
8655                         // deform the normals to make reflections wavey
8656                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8657                         rsurface.batchnormal3f_vertexbuffer = NULL;
8658                         rsurface.batchnormal3f_bufferoffset = 0;
8659                         for (j = 0;j < batchnumvertices;j++)
8660                         {
8661                                 float vertex[3];
8662                                 float *normal = rsurface.batchnormal3f + 3*j;
8663                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8664                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8665                                 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]);
8666                                 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]);
8667                                 VectorNormalize(normal);
8668                         }
8669                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8670                         {
8671 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8673 //                              rsurface.batchsvector3f_bufferoffset = 0;
8674 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8675 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8676 //                              rsurface.batchtvector3f_bufferoffset = 0;
8677                                 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);
8678                         }
8679                         break;
8680                 case Q3DEFORM_WAVE:
8681                         // deform vertex array to make wavey water and flags and such
8682                         waveparms[0] = deform->waveparms[0];
8683                         waveparms[1] = deform->waveparms[1];
8684                         waveparms[2] = deform->waveparms[2];
8685                         waveparms[3] = deform->waveparms[3];
8686                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8687                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8688                         // this is how a divisor of vertex influence on deformation
8689                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8690                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8691 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8692 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8693 //                      rsurface.batchvertex3f_bufferoffset = 0;
8694 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8695 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8696 //                      rsurface.batchnormal3f_bufferoffset = 0;
8697                         for (j = 0;j < batchnumvertices;j++)
8698                         {
8699                                 // if the wavefunc depends on time, evaluate it per-vertex
8700                                 if (waveparms[3])
8701                                 {
8702                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8703                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8704                                 }
8705                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8706                         }
8707                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8708                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8709                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8710                         {
8711 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8713 //                              rsurface.batchsvector3f_bufferoffset = 0;
8714 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8716 //                              rsurface.batchtvector3f_bufferoffset = 0;
8717                                 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);
8718                         }
8719                         break;
8720                 case Q3DEFORM_BULGE:
8721                         // deform vertex array to make the surface have moving bulges
8722 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8723 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8724 //                      rsurface.batchvertex3f_bufferoffset = 0;
8725 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8726 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8727 //                      rsurface.batchnormal3f_bufferoffset = 0;
8728                         for (j = 0;j < batchnumvertices;j++)
8729                         {
8730                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8731                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8732                         }
8733                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8734                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8735                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8736                         {
8737 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8738 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8739 //                              rsurface.batchsvector3f_bufferoffset = 0;
8740 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8741 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8742 //                              rsurface.batchtvector3f_bufferoffset = 0;
8743                                 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);
8744                         }
8745                         break;
8746                 case Q3DEFORM_MOVE:
8747                         // deform vertex array
8748                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8749                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8750                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8751                         VectorScale(deform->parms, scale, waveparms);
8752 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8753 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8754 //                      rsurface.batchvertex3f_bufferoffset = 0;
8755                         for (j = 0;j < batchnumvertices;j++)
8756                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8757                         break;
8758                 }
8759         }
8760
8761         // generate texcoords based on the chosen texcoord source
8762         switch(rsurface.texture->tcgen.tcgen)
8763         {
8764         default:
8765         case Q3TCGEN_TEXTURE:
8766                 break;
8767         case Q3TCGEN_LIGHTMAP:
8768 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8769 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8770 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8771                 if (rsurface.batchtexcoordlightmap2f)
8772                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8773                 break;
8774         case Q3TCGEN_VECTOR:
8775 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8776 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8777 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8778                 for (j = 0;j < batchnumvertices;j++)
8779                 {
8780                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8781                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8782                 }
8783                 break;
8784         case Q3TCGEN_ENVIRONMENT:
8785                 // make environment reflections using a spheremap
8786                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8787                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8788                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8789                 for (j = 0;j < batchnumvertices;j++)
8790                 {
8791                         // identical to Q3A's method, but executed in worldspace so
8792                         // carried models can be shiny too
8793
8794                         float viewer[3], d, reflected[3], worldreflected[3];
8795
8796                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8797                         // VectorNormalize(viewer);
8798
8799                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8800
8801                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8802                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8803                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8804                         // note: this is proportinal to viewer, so we can normalize later
8805
8806                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8807                         VectorNormalize(worldreflected);
8808
8809                         // note: this sphere map only uses world x and z!
8810                         // so positive and negative y will LOOK THE SAME.
8811                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8812                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8813                 }
8814                 break;
8815         }
8816         // the only tcmod that needs software vertex processing is turbulent, so
8817         // check for it here and apply the changes if needed
8818         // and we only support that as the first one
8819         // (handling a mixture of turbulent and other tcmods would be problematic
8820         //  without punting it entirely to a software path)
8821         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8822         {
8823                 amplitude = rsurface.texture->tcmods[0].parms[1];
8824                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8825 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8826 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8827 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8828                 for (j = 0;j < batchnumvertices;j++)
8829                 {
8830                         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);
8831                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8832                 }
8833         }
8834
8835         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8836         {
8837                 // convert the modified arrays to vertex structs
8838 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8839 //              rsurface.batchvertexmeshbuffer = NULL;
8840                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8841                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8842                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8843                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8844                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8845                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8846                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8847                 {
8848                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8849                         {
8850                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8851                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8852                         }
8853                 }
8854                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8855                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8856                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8857                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8858                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8859                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8860                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8861                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8862                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8863         }
8864 }
8865
8866 void RSurf_DrawBatch(void)
8867 {
8868         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8869         // through the pipeline, killing it earlier in the pipeline would have
8870         // per-surface overhead rather than per-batch overhead, so it's best to
8871         // reject it here, before it hits glDraw.
8872         if (rsurface.batchnumtriangles == 0)
8873                 return;
8874 #if 0
8875         // batch debugging code
8876         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8877         {
8878                 int i;
8879                 int j;
8880                 int c;
8881                 const int *e;
8882                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8883                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8884                 {
8885                         c = e[i];
8886                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8887                         {
8888                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8889                                 {
8890                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8891                                                 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);
8892                                         break;
8893                                 }
8894                         }
8895                 }
8896         }
8897 #endif
8898         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);
8899 }
8900
8901 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8902 {
8903         // pick the closest matching water plane
8904         int planeindex, vertexindex, bestplaneindex = -1;
8905         float d, bestd;
8906         vec3_t vert;
8907         const float *v;
8908         r_waterstate_waterplane_t *p;
8909         qboolean prepared = false;
8910         bestd = 0;
8911         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8912         {
8913                 if(p->camera_entity != rsurface.texture->camera_entity)
8914                         continue;
8915                 d = 0;
8916                 if(!prepared)
8917                 {
8918                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8919                         prepared = true;
8920                         if(rsurface.batchnumvertices == 0)
8921                                 break;
8922                 }
8923                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8924                 {
8925                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8926                         d += fabs(PlaneDiff(vert, &p->plane));
8927                 }
8928                 if (bestd > d || bestplaneindex < 0)
8929                 {
8930                         bestd = d;
8931                         bestplaneindex = planeindex;
8932                 }
8933         }
8934         return bestplaneindex;
8935         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8936         // this situation though, as it might be better to render single larger
8937         // batches with useless stuff (backface culled for example) than to
8938         // render multiple smaller batches
8939 }
8940
8941 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8942 {
8943         int i;
8944         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8945         rsurface.passcolor4f_vertexbuffer = 0;
8946         rsurface.passcolor4f_bufferoffset = 0;
8947         for (i = 0;i < rsurface.batchnumvertices;i++)
8948                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8949 }
8950
8951 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8952 {
8953         int i;
8954         float f;
8955         const float *v;
8956         const float *c;
8957         float *c2;
8958         if (rsurface.passcolor4f)
8959         {
8960                 // generate color arrays
8961                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8962                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8963                 rsurface.passcolor4f_vertexbuffer = 0;
8964                 rsurface.passcolor4f_bufferoffset = 0;
8965                 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)
8966                 {
8967                         f = RSurf_FogVertex(v);
8968                         c2[0] = c[0] * f;
8969                         c2[1] = c[1] * f;
8970                         c2[2] = c[2] * f;
8971                         c2[3] = c[3];
8972                 }
8973         }
8974         else
8975         {
8976                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8977                 rsurface.passcolor4f_vertexbuffer = 0;
8978                 rsurface.passcolor4f_bufferoffset = 0;
8979                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8980                 {
8981                         f = RSurf_FogVertex(v);
8982                         c2[0] = f;
8983                         c2[1] = f;
8984                         c2[2] = f;
8985                         c2[3] = 1;
8986                 }
8987         }
8988 }
8989
8990 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8991 {
8992         int i;
8993         float f;
8994         const float *v;
8995         const float *c;
8996         float *c2;
8997         if (!rsurface.passcolor4f)
8998                 return;
8999         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9000         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9001         rsurface.passcolor4f_vertexbuffer = 0;
9002         rsurface.passcolor4f_bufferoffset = 0;
9003         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)
9004         {
9005                 f = RSurf_FogVertex(v);
9006                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9007                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9008                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9009                 c2[3] = c[3];
9010         }
9011 }
9012
9013 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9014 {
9015         int i;
9016         const float *c;
9017         float *c2;
9018         if (!rsurface.passcolor4f)
9019                 return;
9020         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9021         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9022         rsurface.passcolor4f_vertexbuffer = 0;
9023         rsurface.passcolor4f_bufferoffset = 0;
9024         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9025         {
9026                 c2[0] = c[0] * r;
9027                 c2[1] = c[1] * g;
9028                 c2[2] = c[2] * b;
9029                 c2[3] = c[3] * a;
9030         }
9031 }
9032
9033 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9034 {
9035         int i;
9036         const float *c;
9037         float *c2;
9038         if (!rsurface.passcolor4f)
9039                 return;
9040         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9041         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9042         rsurface.passcolor4f_vertexbuffer = 0;
9043         rsurface.passcolor4f_bufferoffset = 0;
9044         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9045         {
9046                 c2[0] = c[0] + r_refdef.scene.ambient;
9047                 c2[1] = c[1] + r_refdef.scene.ambient;
9048                 c2[2] = c[2] + r_refdef.scene.ambient;
9049                 c2[3] = c[3];
9050         }
9051 }
9052
9053 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9054 {
9055         // TODO: optimize
9056         rsurface.passcolor4f = NULL;
9057         rsurface.passcolor4f_vertexbuffer = 0;
9058         rsurface.passcolor4f_bufferoffset = 0;
9059         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9060         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9061         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9062         GL_Color(r, g, b, a);
9063         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9064         RSurf_DrawBatch();
9065 }
9066
9067 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9068 {
9069         // TODO: optimize applyfog && applycolor case
9070         // just apply fog if necessary, and tint the fog color array if necessary
9071         rsurface.passcolor4f = NULL;
9072         rsurface.passcolor4f_vertexbuffer = 0;
9073         rsurface.passcolor4f_bufferoffset = 0;
9074         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9075         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9076         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9077         GL_Color(r, g, b, a);
9078         RSurf_DrawBatch();
9079 }
9080
9081 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9082 {
9083         // TODO: optimize
9084         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9085         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9086         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9087         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9088         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9089         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9090         GL_Color(r, g, b, a);
9091         RSurf_DrawBatch();
9092 }
9093
9094 static void RSurf_DrawBatch_GL11_ClampColor(void)
9095 {
9096         int i;
9097         const float *c1;
9098         float *c2;
9099         if (!rsurface.passcolor4f)
9100                 return;
9101         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9102         {
9103                 c2[0] = bound(0.0f, c1[0], 1.0f);
9104                 c2[1] = bound(0.0f, c1[1], 1.0f);
9105                 c2[2] = bound(0.0f, c1[2], 1.0f);
9106                 c2[3] = bound(0.0f, c1[3], 1.0f);
9107         }
9108 }
9109
9110 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9111 {
9112         int i;
9113         float f;
9114         const float *v;
9115         const float *n;
9116         float *c;
9117         //vec3_t eyedir;
9118
9119         // fake shading
9120         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121         rsurface.passcolor4f_vertexbuffer = 0;
9122         rsurface.passcolor4f_bufferoffset = 0;
9123         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)
9124         {
9125                 f = -DotProduct(r_refdef.view.forward, n);
9126                 f = max(0, f);
9127                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9128                 f *= r_refdef.lightmapintensity;
9129                 Vector4Set(c, f, f, f, 1);
9130         }
9131 }
9132
9133 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9134 {
9135         RSurf_DrawBatch_GL11_ApplyFakeLight();
9136         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9137         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9138         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9139         GL_Color(r, g, b, a);
9140         RSurf_DrawBatch();
9141 }
9142
9143 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9144 {
9145         int i;
9146         float f;
9147         float alpha;
9148         const float *v;
9149         const float *n;
9150         float *c;
9151         vec3_t ambientcolor;
9152         vec3_t diffusecolor;
9153         vec3_t lightdir;
9154         // TODO: optimize
9155         // model lighting
9156         VectorCopy(rsurface.modellight_lightdir, lightdir);
9157         f = 0.5f * r_refdef.lightmapintensity;
9158         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9159         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9160         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9161         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9162         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9163         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9164         alpha = *a;
9165         if (VectorLength2(diffusecolor) > 0)
9166         {
9167                 // q3-style directional shading
9168                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9169                 rsurface.passcolor4f_vertexbuffer = 0;
9170                 rsurface.passcolor4f_bufferoffset = 0;
9171                 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)
9172                 {
9173                         if ((f = DotProduct(n, lightdir)) > 0)
9174                                 VectorMA(ambientcolor, f, diffusecolor, c);
9175                         else
9176                                 VectorCopy(ambientcolor, c);
9177                         c[3] = alpha;
9178                 }
9179                 *r = 1;
9180                 *g = 1;
9181                 *b = 1;
9182                 *a = 1;
9183                 *applycolor = false;
9184         }
9185         else
9186         {
9187                 *r = ambientcolor[0];
9188                 *g = ambientcolor[1];
9189                 *b = ambientcolor[2];
9190                 rsurface.passcolor4f = NULL;
9191                 rsurface.passcolor4f_vertexbuffer = 0;
9192                 rsurface.passcolor4f_bufferoffset = 0;
9193         }
9194 }
9195
9196 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9197 {
9198         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9199         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9200         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9201         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9202         GL_Color(r, g, b, a);
9203         RSurf_DrawBatch();
9204 }
9205
9206 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9207 {
9208         int i;
9209         float f;
9210         const float *v;
9211         float *c;
9212         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9213         {
9214                 f = 1 - RSurf_FogVertex(v);
9215                 c[0] = r;
9216                 c[1] = g;
9217                 c[2] = b;
9218                 c[3] = f * a;
9219         }
9220 }
9221
9222 void RSurf_SetupDepthAndCulling(void)
9223 {
9224         // submodels are biased to avoid z-fighting with world surfaces that they
9225         // may be exactly overlapping (avoids z-fighting artifacts on certain
9226         // doors and things in Quake maps)
9227         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9228         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9229         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9230         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9231 }
9232
9233 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9234 {
9235         // transparent sky would be ridiculous
9236         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9237                 return;
9238         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9239         skyrenderlater = true;
9240         RSurf_SetupDepthAndCulling();
9241         GL_DepthMask(true);
9242         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9243         // skymasking on them, and Quake3 never did sky masking (unlike
9244         // software Quake and software Quake2), so disable the sky masking
9245         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9246         // and skymasking also looks very bad when noclipping outside the
9247         // level, so don't use it then either.
9248         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9249         {
9250                 R_Mesh_ResetTextureState();
9251                 if (skyrendermasked)
9252                 {
9253                         R_SetupShader_DepthOrShadow();
9254                         // depth-only (masking)
9255                         GL_ColorMask(0,0,0,0);
9256                         // just to make sure that braindead drivers don't draw
9257                         // anything despite that colormask...
9258                         GL_BlendFunc(GL_ZERO, GL_ONE);
9259                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9260                         if (rsurface.batchvertex3fbuffer)
9261                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9262                         else
9263                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9264                 }
9265                 else
9266                 {
9267                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9268                         // fog sky
9269                         GL_BlendFunc(GL_ONE, GL_ZERO);
9270                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9271                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9272                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9273                 }
9274                 RSurf_DrawBatch();
9275                 if (skyrendermasked)
9276                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9277         }
9278         R_Mesh_ResetTextureState();
9279         GL_Color(1, 1, 1, 1);
9280 }
9281
9282 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9283 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9284 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9285 {
9286         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9287                 return;
9288         if (prepass)
9289         {
9290                 // render screenspace normalmap to texture
9291                 GL_DepthMask(true);
9292                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9293                 RSurf_DrawBatch();
9294                 return;
9295         }
9296
9297         // bind lightmap texture
9298
9299         // water/refraction/reflection/camera surfaces have to be handled specially
9300         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9301         {
9302                 int start, end, startplaneindex;
9303                 for (start = 0;start < texturenumsurfaces;start = end)
9304                 {
9305                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9306                         if(startplaneindex < 0)
9307                         {
9308                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9309                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9310                                 end = start + 1;
9311                                 continue;
9312                         }
9313                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9314                                 ;
9315                         // now that we have a batch using the same planeindex, render it
9316                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9317                         {
9318                                 // render water or distortion background
9319                                 GL_DepthMask(true);
9320                                 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));
9321                                 RSurf_DrawBatch();
9322                                 // blend surface on top
9323                                 GL_DepthMask(false);
9324                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9325                                 RSurf_DrawBatch();
9326                         }
9327                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9328                         {
9329                                 // render surface with reflection texture as input
9330                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9331                                 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));
9332                                 RSurf_DrawBatch();
9333                         }
9334                 }
9335                 return;
9336         }
9337
9338         // render surface batch normally
9339         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9340         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9341         RSurf_DrawBatch();
9342 }
9343
9344 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9345 {
9346         // OpenGL 1.3 path - anything not completely ancient
9347         qboolean applycolor;
9348         qboolean applyfog;
9349         int layerindex;
9350         const texturelayer_t *layer;
9351         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);
9352         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9353
9354         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9355         {
9356                 vec4_t layercolor;
9357                 int layertexrgbscale;
9358                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9359                 {
9360                         if (layerindex == 0)
9361                                 GL_AlphaTest(true);
9362                         else
9363                         {
9364                                 GL_AlphaTest(false);
9365                                 GL_DepthFunc(GL_EQUAL);
9366                         }
9367                 }
9368                 GL_DepthMask(layer->depthmask && writedepth);
9369                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9370                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9371                 {
9372                         layertexrgbscale = 4;
9373                         VectorScale(layer->color, 0.25f, layercolor);
9374                 }
9375                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9376                 {
9377                         layertexrgbscale = 2;
9378                         VectorScale(layer->color, 0.5f, layercolor);
9379                 }
9380                 else
9381                 {
9382                         layertexrgbscale = 1;
9383                         VectorScale(layer->color, 1.0f, layercolor);
9384                 }
9385                 layercolor[3] = layer->color[3];
9386                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9387                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9388                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9389                 switch (layer->type)
9390                 {
9391                 case TEXTURELAYERTYPE_LITTEXTURE:
9392                         // single-pass lightmapped texture with 2x rgbscale
9393                         R_Mesh_TexBind(0, r_texture_white);
9394                         R_Mesh_TexMatrix(0, NULL);
9395                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9396                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9397                         R_Mesh_TexBind(1, layer->texture);
9398                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9399                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9400                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9401                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9402                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9403                         else if (FAKELIGHT_ENABLED)
9404                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9405                         else if (rsurface.uselightmaptexture)
9406                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9407                         else
9408                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9409                         break;
9410                 case TEXTURELAYERTYPE_TEXTURE:
9411                         // singletexture unlit texture with transparency support
9412                         R_Mesh_TexBind(0, layer->texture);
9413                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9414                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9415                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9416                         R_Mesh_TexBind(1, 0);
9417                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9418                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9419                         break;
9420                 case TEXTURELAYERTYPE_FOG:
9421                         // singletexture fogging
9422                         if (layer->texture)
9423                         {
9424                                 R_Mesh_TexBind(0, layer->texture);
9425                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9426                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9427                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9428                         }
9429                         else
9430                         {
9431                                 R_Mesh_TexBind(0, 0);
9432                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9433                         }
9434                         R_Mesh_TexBind(1, 0);
9435                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9436                         // generate a color array for the fog pass
9437                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9438                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9439                         RSurf_DrawBatch();
9440                         break;
9441                 default:
9442                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9443                 }
9444         }
9445         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9446         {
9447                 GL_DepthFunc(GL_LEQUAL);
9448                 GL_AlphaTest(false);
9449         }
9450 }
9451
9452 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9453 {
9454         // OpenGL 1.1 - crusty old voodoo path
9455         qboolean applyfog;
9456         int layerindex;
9457         const texturelayer_t *layer;
9458         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9459         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9460
9461         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9462         {
9463                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9464                 {
9465                         if (layerindex == 0)
9466                                 GL_AlphaTest(true);
9467                         else
9468                         {
9469                                 GL_AlphaTest(false);
9470                                 GL_DepthFunc(GL_EQUAL);
9471                         }
9472                 }
9473                 GL_DepthMask(layer->depthmask && writedepth);
9474                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9475                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9476                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9477                 switch (layer->type)
9478                 {
9479                 case TEXTURELAYERTYPE_LITTEXTURE:
9480                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9481                         {
9482                                 // two-pass lit texture with 2x rgbscale
9483                                 // first the lightmap pass
9484                                 R_Mesh_TexBind(0, r_texture_white);
9485                                 R_Mesh_TexMatrix(0, NULL);
9486                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9487                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9488                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9489                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9490                                 else if (FAKELIGHT_ENABLED)
9491                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9492                                 else if (rsurface.uselightmaptexture)
9493                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9494                                 else
9495                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9496                                 // then apply the texture to it
9497                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9498                                 R_Mesh_TexBind(0, layer->texture);
9499                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9500                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9501                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9502                                 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);
9503                         }
9504                         else
9505                         {
9506                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9507                                 R_Mesh_TexBind(0, layer->texture);
9508                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9509                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9510                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9511                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9512                                         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);
9513                                 else
9514                                         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);
9515                         }
9516                         break;
9517                 case TEXTURELAYERTYPE_TEXTURE:
9518                         // singletexture unlit texture with transparency support
9519                         R_Mesh_TexBind(0, layer->texture);
9520                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9521                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9522                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9523                         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);
9524                         break;
9525                 case TEXTURELAYERTYPE_FOG:
9526                         // singletexture fogging
9527                         if (layer->texture)
9528                         {
9529                                 R_Mesh_TexBind(0, layer->texture);
9530                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9531                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9532                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9533                         }
9534                         else
9535                         {
9536                                 R_Mesh_TexBind(0, 0);
9537                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9538                         }
9539                         // generate a color array for the fog pass
9540                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9541                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9542                         RSurf_DrawBatch();
9543                         break;
9544                 default:
9545                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9546                 }
9547         }
9548         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9549         {
9550                 GL_DepthFunc(GL_LEQUAL);
9551                 GL_AlphaTest(false);
9552         }
9553 }
9554
9555 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9556 {
9557         int vi;
9558         int j;
9559         r_vertexgeneric_t *batchvertex;
9560         float c[4];
9561
9562 //      R_Mesh_ResetTextureState();
9563         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9564
9565         if(rsurface.texture && rsurface.texture->currentskinframe)
9566         {
9567                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9568                 c[3] *= rsurface.texture->currentalpha;
9569         }
9570         else
9571         {
9572                 c[0] = 1;
9573                 c[1] = 0;
9574                 c[2] = 1;
9575                 c[3] = 1;
9576         }
9577
9578         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9579         {
9580                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9581                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9582                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9583         }
9584
9585         // brighten it up (as texture value 127 means "unlit")
9586         c[0] *= 2 * r_refdef.view.colorscale;
9587         c[1] *= 2 * r_refdef.view.colorscale;
9588         c[2] *= 2 * r_refdef.view.colorscale;
9589
9590         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9591                 c[3] *= r_wateralpha.value;
9592
9593         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9594         {
9595                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9596                 GL_DepthMask(false);
9597         }
9598         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9599         {
9600                 GL_BlendFunc(GL_ONE, GL_ONE);
9601                 GL_DepthMask(false);
9602         }
9603         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9604         {
9605                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9606                 GL_DepthMask(false);
9607         }
9608         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9609         {
9610                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9611                 GL_DepthMask(false);
9612         }
9613         else
9614         {
9615                 GL_BlendFunc(GL_ONE, GL_ZERO);
9616                 GL_DepthMask(writedepth);
9617         }
9618
9619         if (r_showsurfaces.integer == 3)
9620         {
9621                 rsurface.passcolor4f = NULL;
9622
9623                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9624                 {
9625                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9626
9627                         rsurface.passcolor4f = NULL;
9628                         rsurface.passcolor4f_vertexbuffer = 0;
9629                         rsurface.passcolor4f_bufferoffset = 0;
9630                 }
9631                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9632                 {
9633                         qboolean applycolor = true;
9634                         float one = 1.0;
9635
9636                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9637
9638                         r_refdef.lightmapintensity = 1;
9639                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9640                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9641                 }
9642                 else if (FAKELIGHT_ENABLED)
9643                 {
9644                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9645
9646                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9647                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9648                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9649                 }
9650                 else
9651                 {
9652                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653
9654                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9655                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9656                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9657                 }
9658
9659                 if(!rsurface.passcolor4f)
9660                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9661
9662                 RSurf_DrawBatch_GL11_ApplyAmbient();
9663                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9664                 if(r_refdef.fogenabled)
9665                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9666                 RSurf_DrawBatch_GL11_ClampColor();
9667
9668                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9669                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9670                 RSurf_DrawBatch();
9671         }
9672         else if (!r_refdef.view.showdebug)
9673         {
9674                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9675                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9676                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9677                 {
9678                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9679                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9680                 }
9681                 R_Mesh_PrepareVertices_Generic_Unlock();
9682                 RSurf_DrawBatch();
9683         }
9684         else if (r_showsurfaces.integer == 4)
9685         {
9686                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9687                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9688                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9689                 {
9690                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9691                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9692                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9693                 }
9694                 R_Mesh_PrepareVertices_Generic_Unlock();
9695                 RSurf_DrawBatch();
9696         }
9697         else if (r_showsurfaces.integer == 2)
9698         {
9699                 const int *e;
9700                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9701                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9702                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9703                 {
9704                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9705                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9706                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9707                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9708                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9709                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9710                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9711                 }
9712                 R_Mesh_PrepareVertices_Generic_Unlock();
9713                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9714         }
9715         else
9716         {
9717                 int texturesurfaceindex;
9718                 int k;
9719                 const msurface_t *surface;
9720                 float surfacecolor4f[4];
9721                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9722                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9723                 vi = 0;
9724                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9725                 {
9726                         surface = texturesurfacelist[texturesurfaceindex];
9727                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9728                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9729                         for (j = 0;j < surface->num_vertices;j++)
9730                         {
9731                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9732                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9733                                 vi++;
9734                         }
9735                 }
9736                 R_Mesh_PrepareVertices_Generic_Unlock();
9737                 RSurf_DrawBatch();
9738         }
9739 }
9740
9741 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9742 {
9743         CHECKGLERROR
9744         RSurf_SetupDepthAndCulling();
9745         if (r_showsurfaces.integer)
9746         {
9747                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9748                 return;
9749         }
9750         switch (vid.renderpath)
9751         {
9752         case RENDERPATH_GL20:
9753         case RENDERPATH_D3D9:
9754         case RENDERPATH_D3D10:
9755         case RENDERPATH_D3D11:
9756         case RENDERPATH_SOFT:
9757         case RENDERPATH_GLES2:
9758                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9759                 break;
9760         case RENDERPATH_GL13:
9761                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9762                 break;
9763         case RENDERPATH_GL11:
9764                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9765                 break;
9766         }
9767         CHECKGLERROR
9768 }
9769
9770 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9771 {
9772         CHECKGLERROR
9773         RSurf_SetupDepthAndCulling();
9774         if (r_showsurfaces.integer)
9775         {
9776                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9777                 return;
9778         }
9779         switch (vid.renderpath)
9780         {
9781         case RENDERPATH_GL20:
9782         case RENDERPATH_D3D9:
9783         case RENDERPATH_D3D10:
9784         case RENDERPATH_D3D11:
9785         case RENDERPATH_SOFT:
9786         case RENDERPATH_GLES2:
9787                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9788                 break;
9789         case RENDERPATH_GL13:
9790                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9791                 break;
9792         case RENDERPATH_GL11:
9793                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9794                 break;
9795         }
9796         CHECKGLERROR
9797 }
9798
9799 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9800 {
9801         int i, j;
9802         int texturenumsurfaces, endsurface;
9803         texture_t *texture;
9804         const msurface_t *surface;
9805 #define MAXBATCH_TRANSPARENTSURFACES 256
9806         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9807
9808         // if the model is static it doesn't matter what value we give for
9809         // wantnormals and wanttangents, so this logic uses only rules applicable
9810         // to a model, knowing that they are meaningless otherwise
9811         if (ent == r_refdef.scene.worldentity)
9812                 RSurf_ActiveWorldEntity();
9813         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9814                 RSurf_ActiveModelEntity(ent, false, false, false);
9815         else
9816         {
9817                 switch (vid.renderpath)
9818                 {
9819                 case RENDERPATH_GL20:
9820                 case RENDERPATH_D3D9:
9821                 case RENDERPATH_D3D10:
9822                 case RENDERPATH_D3D11:
9823                 case RENDERPATH_SOFT:
9824                 case RENDERPATH_GLES2:
9825                         RSurf_ActiveModelEntity(ent, true, true, false);
9826                         break;
9827                 case RENDERPATH_GL13:
9828                 case RENDERPATH_GL11:
9829                         RSurf_ActiveModelEntity(ent, true, false, false);
9830                         break;
9831                 }
9832         }
9833
9834         if (r_transparentdepthmasking.integer)
9835         {
9836                 qboolean setup = false;
9837                 for (i = 0;i < numsurfaces;i = j)
9838                 {
9839                         j = i + 1;
9840                         surface = rsurface.modelsurfaces + surfacelist[i];
9841                         texture = surface->texture;
9842                         rsurface.texture = R_GetCurrentTexture(texture);
9843                         rsurface.lightmaptexture = NULL;
9844                         rsurface.deluxemaptexture = NULL;
9845                         rsurface.uselightmaptexture = false;
9846                         // scan ahead until we find a different texture
9847                         endsurface = min(i + 1024, numsurfaces);
9848                         texturenumsurfaces = 0;
9849                         texturesurfacelist[texturenumsurfaces++] = surface;
9850                         for (;j < endsurface;j++)
9851                         {
9852                                 surface = rsurface.modelsurfaces + surfacelist[j];
9853                                 if (texture != surface->texture)
9854                                         break;
9855                                 texturesurfacelist[texturenumsurfaces++] = surface;
9856                         }
9857                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9858                                 continue;
9859                         // render the range of surfaces as depth
9860                         if (!setup)
9861                         {
9862                                 setup = true;
9863                                 GL_ColorMask(0,0,0,0);
9864                                 GL_Color(1,1,1,1);
9865                                 GL_DepthTest(true);
9866                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9867                                 GL_DepthMask(true);
9868 //                              R_Mesh_ResetTextureState();
9869                                 R_SetupShader_DepthOrShadow();
9870                         }
9871                         RSurf_SetupDepthAndCulling();
9872                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9873                         if (rsurface.batchvertex3fbuffer)
9874                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9875                         else
9876                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9877                         RSurf_DrawBatch();
9878                 }
9879                 if (setup)
9880                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9881         }
9882
9883         for (i = 0;i < numsurfaces;i = j)
9884         {
9885                 j = i + 1;
9886                 surface = rsurface.modelsurfaces + surfacelist[i];
9887                 texture = surface->texture;
9888                 rsurface.texture = R_GetCurrentTexture(texture);
9889                 // scan ahead until we find a different texture
9890                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9891                 texturenumsurfaces = 0;
9892                 texturesurfacelist[texturenumsurfaces++] = surface;
9893                 if(FAKELIGHT_ENABLED)
9894                 {
9895                         rsurface.lightmaptexture = NULL;
9896                         rsurface.deluxemaptexture = NULL;
9897                         rsurface.uselightmaptexture = false;
9898                         for (;j < endsurface;j++)
9899                         {
9900                                 surface = rsurface.modelsurfaces + surfacelist[j];
9901                                 if (texture != surface->texture)
9902                                         break;
9903                                 texturesurfacelist[texturenumsurfaces++] = surface;
9904                         }
9905                 }
9906                 else
9907                 {
9908                         rsurface.lightmaptexture = surface->lightmaptexture;
9909                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9910                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9911                         for (;j < endsurface;j++)
9912                         {
9913                                 surface = rsurface.modelsurfaces + surfacelist[j];
9914                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9915                                         break;
9916                                 texturesurfacelist[texturenumsurfaces++] = surface;
9917                         }
9918                 }
9919                 // render the range of surfaces
9920                 if (ent == r_refdef.scene.worldentity)
9921                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9922                 else
9923                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9924         }
9925         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9926 }
9927
9928 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9929 {
9930         // transparent surfaces get pushed off into the transparent queue
9931         int surfacelistindex;
9932         const msurface_t *surface;
9933         vec3_t tempcenter, center;
9934         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9935         {
9936                 surface = texturesurfacelist[surfacelistindex];
9937                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9938                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9939                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9940                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9941                 if (queueentity->transparent_offset) // transparent offset
9942                 {
9943                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9944                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9945                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9946                 }
9947                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9948         }
9949 }
9950
9951 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9952 {
9953         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9954                 return;
9955         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9956                 return;
9957         RSurf_SetupDepthAndCulling();
9958         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9959         if (rsurface.batchvertex3fbuffer)
9960                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9961         else
9962                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9963         RSurf_DrawBatch();
9964 }
9965
9966 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9967 {
9968         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9969         CHECKGLERROR
9970         if (depthonly)
9971                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9972         else if (prepass)
9973         {
9974                 if (!rsurface.texture->currentnumlayers)
9975                         return;
9976                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9977                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9978                 else
9979                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9980         }
9981         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9982                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9983         else if (!rsurface.texture->currentnumlayers)
9984                 return;
9985         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9986         {
9987                 // in the deferred case, transparent surfaces were queued during prepass
9988                 if (!r_shadow_usingdeferredprepass)
9989                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9990         }
9991         else
9992         {
9993                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9994                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9995         }
9996         CHECKGLERROR
9997 }
9998
9999 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10000 {
10001         int i, j;
10002         texture_t *texture;
10003         R_FrameData_SetMark();
10004         // break the surface list down into batches by texture and use of lightmapping
10005         for (i = 0;i < numsurfaces;i = j)
10006         {
10007                 j = i + 1;
10008                 // texture is the base texture pointer, rsurface.texture is the
10009                 // current frame/skin the texture is directing us to use (for example
10010                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10011                 // use skin 1 instead)
10012                 texture = surfacelist[i]->texture;
10013                 rsurface.texture = R_GetCurrentTexture(texture);
10014                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10015                 {
10016                         // if this texture is not the kind we want, skip ahead to the next one
10017                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10018                                 ;
10019                         continue;
10020                 }
10021                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10022                 {
10023                         rsurface.lightmaptexture = NULL;
10024                         rsurface.deluxemaptexture = NULL;
10025                         rsurface.uselightmaptexture = false;
10026                         // simply scan ahead until we find a different texture or lightmap state
10027                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10028                                 ;
10029                 }
10030                 else
10031                 {
10032                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10033                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10034                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10035                         // simply scan ahead until we find a different texture or lightmap state
10036                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10037                                 ;
10038                 }
10039                 // render the range of surfaces
10040                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10041         }
10042         R_FrameData_ReturnToMark();
10043 }
10044
10045 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10046 {
10047         CHECKGLERROR
10048         if (depthonly)
10049                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10050         else if (prepass)
10051         {
10052                 if (!rsurface.texture->currentnumlayers)
10053                         return;
10054                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10055                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10056                 else
10057                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10058         }
10059         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10060                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10061         else if (!rsurface.texture->currentnumlayers)
10062                 return;
10063         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10064         {
10065                 // in the deferred case, transparent surfaces were queued during prepass
10066                 if (!r_shadow_usingdeferredprepass)
10067                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10068         }
10069         else
10070         {
10071                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10072                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10073         }
10074         CHECKGLERROR
10075 }
10076
10077 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10078 {
10079         int i, j;
10080         texture_t *texture;
10081         R_FrameData_SetMark();
10082         // break the surface list down into batches by texture and use of lightmapping
10083         for (i = 0;i < numsurfaces;i = j)
10084         {
10085                 j = i + 1;
10086                 // texture is the base texture pointer, rsurface.texture is the
10087                 // current frame/skin the texture is directing us to use (for example
10088                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10089                 // use skin 1 instead)
10090                 texture = surfacelist[i]->texture;
10091                 rsurface.texture = R_GetCurrentTexture(texture);
10092                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10093                 {
10094                         // if this texture is not the kind we want, skip ahead to the next one
10095                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10096                                 ;
10097                         continue;
10098                 }
10099                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10100                 {
10101                         rsurface.lightmaptexture = NULL;
10102                         rsurface.deluxemaptexture = NULL;
10103                         rsurface.uselightmaptexture = false;
10104                         // simply scan ahead until we find a different texture or lightmap state
10105                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10106                                 ;
10107                 }
10108                 else
10109                 {
10110                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10111                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10112                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10113                         // simply scan ahead until we find a different texture or lightmap state
10114                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10115                                 ;
10116                 }
10117                 // render the range of surfaces
10118                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10119         }
10120         R_FrameData_ReturnToMark();
10121 }
10122
10123 float locboxvertex3f[6*4*3] =
10124 {
10125         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10126         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10127         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10128         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10129         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10130         1,0,0, 0,0,0, 0,1,0, 1,1,0
10131 };
10132
10133 unsigned short locboxelements[6*2*3] =
10134 {
10135          0, 1, 2, 0, 2, 3,
10136          4, 5, 6, 4, 6, 7,
10137          8, 9,10, 8,10,11,
10138         12,13,14, 12,14,15,
10139         16,17,18, 16,18,19,
10140         20,21,22, 20,22,23
10141 };
10142
10143 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10144 {
10145         int i, j;
10146         cl_locnode_t *loc = (cl_locnode_t *)ent;
10147         vec3_t mins, size;
10148         float vertex3f[6*4*3];
10149         CHECKGLERROR
10150         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10151         GL_DepthMask(false);
10152         GL_DepthRange(0, 1);
10153         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10154         GL_DepthTest(true);
10155         GL_CullFace(GL_NONE);
10156         R_EntityMatrix(&identitymatrix);
10157
10158 //      R_Mesh_ResetTextureState();
10159
10160         i = surfacelist[0];
10161         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10162                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10163                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10164                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10165
10166         if (VectorCompare(loc->mins, loc->maxs))
10167         {
10168                 VectorSet(size, 2, 2, 2);
10169                 VectorMA(loc->mins, -0.5f, size, mins);
10170         }
10171         else
10172         {
10173                 VectorCopy(loc->mins, mins);
10174                 VectorSubtract(loc->maxs, loc->mins, size);
10175         }
10176
10177         for (i = 0;i < 6*4*3;)
10178                 for (j = 0;j < 3;j++, i++)
10179                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10180
10181         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10182         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10183         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10184 }
10185
10186 void R_DrawLocs(void)
10187 {
10188         int index;
10189         cl_locnode_t *loc, *nearestloc;
10190         vec3_t center;
10191         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10192         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10193         {
10194                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10195                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10196         }
10197 }
10198
10199 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10200 {
10201         if (decalsystem->decals)
10202                 Mem_Free(decalsystem->decals);
10203         memset(decalsystem, 0, sizeof(*decalsystem));
10204 }
10205
10206 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)
10207 {
10208         tridecal_t *decal;
10209         tridecal_t *decals;
10210         int i;
10211
10212         // expand or initialize the system
10213         if (decalsystem->maxdecals <= decalsystem->numdecals)
10214         {
10215                 decalsystem_t old = *decalsystem;
10216                 qboolean useshortelements;
10217                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10218                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10219                 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)));
10220                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10221                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10222                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10223                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10224                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10225                 if (decalsystem->numdecals)
10226                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10227                 if (old.decals)
10228                         Mem_Free(old.decals);
10229                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10230                         decalsystem->element3i[i] = i;
10231                 if (useshortelements)
10232                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10233                                 decalsystem->element3s[i] = i;
10234         }
10235
10236         // grab a decal and search for another free slot for the next one
10237         decals = decalsystem->decals;
10238         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10239         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10240                 ;
10241         decalsystem->freedecal = i;
10242         if (decalsystem->numdecals <= i)
10243                 decalsystem->numdecals = i + 1;
10244
10245         // initialize the decal
10246         decal->lived = 0;
10247         decal->triangleindex = triangleindex;
10248         decal->surfaceindex = surfaceindex;
10249         decal->decalsequence = decalsequence;
10250         decal->color4f[0][0] = c0[0];
10251         decal->color4f[0][1] = c0[1];
10252         decal->color4f[0][2] = c0[2];
10253         decal->color4f[0][3] = 1;
10254         decal->color4f[1][0] = c1[0];
10255         decal->color4f[1][1] = c1[1];
10256         decal->color4f[1][2] = c1[2];
10257         decal->color4f[1][3] = 1;
10258         decal->color4f[2][0] = c2[0];
10259         decal->color4f[2][1] = c2[1];
10260         decal->color4f[2][2] = c2[2];
10261         decal->color4f[2][3] = 1;
10262         decal->vertex3f[0][0] = v0[0];
10263         decal->vertex3f[0][1] = v0[1];
10264         decal->vertex3f[0][2] = v0[2];
10265         decal->vertex3f[1][0] = v1[0];
10266         decal->vertex3f[1][1] = v1[1];
10267         decal->vertex3f[1][2] = v1[2];
10268         decal->vertex3f[2][0] = v2[0];
10269         decal->vertex3f[2][1] = v2[1];
10270         decal->vertex3f[2][2] = v2[2];
10271         decal->texcoord2f[0][0] = t0[0];
10272         decal->texcoord2f[0][1] = t0[1];
10273         decal->texcoord2f[1][0] = t1[0];
10274         decal->texcoord2f[1][1] = t1[1];
10275         decal->texcoord2f[2][0] = t2[0];
10276         decal->texcoord2f[2][1] = t2[1];
10277 }
10278
10279 extern cvar_t cl_decals_bias;
10280 extern cvar_t cl_decals_models;
10281 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10282 // baseparms, parms, temps
10283 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)
10284 {
10285         int cornerindex;
10286         int index;
10287         float v[9][3];
10288         const float *vertex3f;
10289         const float *normal3f;
10290         int numpoints;
10291         float points[2][9][3];
10292         float temp[3];
10293         float tc[9][2];
10294         float f;
10295         float c[9][4];
10296         const int *e;
10297
10298         e = rsurface.modelelement3i + 3*triangleindex;
10299
10300         vertex3f = rsurface.modelvertex3f;
10301         normal3f = rsurface.modelnormal3f;
10302
10303         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10304         {
10305                 index = 3*e[cornerindex];
10306                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10307         }
10308         // cull backfaces
10309         //TriangleNormal(v[0], v[1], v[2], normal);
10310         //if (DotProduct(normal, localnormal) < 0.0f)
10311         //      continue;
10312         // clip by each of the box planes formed from the projection matrix
10313         // if anything survives, we emit the decal
10314         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]);
10315         if (numpoints < 3)
10316                 return;
10317         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]);
10318         if (numpoints < 3)
10319                 return;
10320         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]);
10321         if (numpoints < 3)
10322                 return;
10323         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]);
10324         if (numpoints < 3)
10325                 return;
10326         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]);
10327         if (numpoints < 3)
10328                 return;
10329         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]);
10330         if (numpoints < 3)
10331                 return;
10332         // some part of the triangle survived, so we have to accept it...
10333         if (dynamic)
10334         {
10335                 // dynamic always uses the original triangle
10336                 numpoints = 3;
10337                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10338                 {
10339                         index = 3*e[cornerindex];
10340                         VectorCopy(vertex3f + index, v[cornerindex]);
10341                 }
10342         }
10343         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10344         {
10345                 // convert vertex positions to texcoords
10346                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10347                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10348                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10349                 // calculate distance fade from the projection origin
10350                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10351                 f = bound(0.0f, f, 1.0f);
10352                 c[cornerindex][0] = r * f;
10353                 c[cornerindex][1] = g * f;
10354                 c[cornerindex][2] = b * f;
10355                 c[cornerindex][3] = 1.0f;
10356                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10357         }
10358         if (dynamic)
10359                 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);
10360         else
10361                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10362                         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);
10363 }
10364 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)
10365 {
10366         matrix4x4_t projection;
10367         decalsystem_t *decalsystem;
10368         qboolean dynamic;
10369         dp_model_t *model;
10370         const msurface_t *surface;
10371         const msurface_t *surfaces;
10372         const int *surfacelist;
10373         const texture_t *texture;
10374         int numtriangles;
10375         int numsurfacelist;
10376         int surfacelistindex;
10377         int surfaceindex;
10378         int triangleindex;
10379         float localorigin[3];
10380         float localnormal[3];
10381         float localmins[3];
10382         float localmaxs[3];
10383         float localsize;
10384         //float normal[3];
10385         float planes[6][4];
10386         float angles[3];
10387         bih_t *bih;
10388         int bih_triangles_count;
10389         int bih_triangles[256];
10390         int bih_surfaces[256];
10391
10392         decalsystem = &ent->decalsystem;
10393         model = ent->model;
10394         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10395         {
10396                 R_DecalSystem_Reset(&ent->decalsystem);
10397                 return;
10398         }
10399
10400         if (!model->brush.data_leafs && !cl_decals_models.integer)
10401         {
10402                 if (decalsystem->model)
10403                         R_DecalSystem_Reset(decalsystem);
10404                 return;
10405         }
10406
10407         if (decalsystem->model != model)
10408                 R_DecalSystem_Reset(decalsystem);
10409         decalsystem->model = model;
10410
10411         RSurf_ActiveModelEntity(ent, true, false, false);
10412
10413         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10414         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10415         VectorNormalize(localnormal);
10416         localsize = worldsize*rsurface.inversematrixscale;
10417         localmins[0] = localorigin[0] - localsize;
10418         localmins[1] = localorigin[1] - localsize;
10419         localmins[2] = localorigin[2] - localsize;
10420         localmaxs[0] = localorigin[0] + localsize;
10421         localmaxs[1] = localorigin[1] + localsize;
10422         localmaxs[2] = localorigin[2] + localsize;
10423
10424         //VectorCopy(localnormal, planes[4]);
10425         //VectorVectors(planes[4], planes[2], planes[0]);
10426         AnglesFromVectors(angles, localnormal, NULL, false);
10427         AngleVectors(angles, planes[0], planes[2], planes[4]);
10428         VectorNegate(planes[0], planes[1]);
10429         VectorNegate(planes[2], planes[3]);
10430         VectorNegate(planes[4], planes[5]);
10431         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10432         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10433         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10434         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10435         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10436         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10437
10438 #if 1
10439 // works
10440 {
10441         matrix4x4_t forwardprojection;
10442         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10443         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10444 }
10445 #else
10446 // broken
10447 {
10448         float projectionvector[4][3];
10449         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10450         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10451         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10452         projectionvector[0][0] = planes[0][0] * ilocalsize;
10453         projectionvector[0][1] = planes[1][0] * ilocalsize;
10454         projectionvector[0][2] = planes[2][0] * ilocalsize;
10455         projectionvector[1][0] = planes[0][1] * ilocalsize;
10456         projectionvector[1][1] = planes[1][1] * ilocalsize;
10457         projectionvector[1][2] = planes[2][1] * ilocalsize;
10458         projectionvector[2][0] = planes[0][2] * ilocalsize;
10459         projectionvector[2][1] = planes[1][2] * ilocalsize;
10460         projectionvector[2][2] = planes[2][2] * ilocalsize;
10461         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10462         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10463         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10464         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10465 }
10466 #endif
10467
10468         dynamic = model->surfmesh.isanimated;
10469         numsurfacelist = model->nummodelsurfaces;
10470         surfacelist = model->sortedmodelsurfaces;
10471         surfaces = model->data_surfaces;
10472
10473         bih = NULL;
10474         bih_triangles_count = -1;
10475         if(!dynamic)
10476         {
10477                 if(model->render_bih.numleafs)
10478                         bih = &model->render_bih;
10479                 else if(model->collision_bih.numleafs)
10480                         bih = &model->collision_bih;
10481         }
10482         if(bih)
10483                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10484         if(bih_triangles_count == 0)
10485                 return;
10486         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10487                 return;
10488         if(bih_triangles_count > 0)
10489         {
10490                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10491                 {
10492                         surfaceindex = bih_surfaces[triangleindex];
10493                         surface = surfaces + surfaceindex;
10494                         texture = surface->texture;
10495                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10496                                 continue;
10497                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10498                                 continue;
10499                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10500                 }
10501         }
10502         else
10503         {
10504                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10505                 {
10506                         surfaceindex = surfacelist[surfacelistindex];
10507                         surface = surfaces + surfaceindex;
10508                         // check cull box first because it rejects more than any other check
10509                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10510                                 continue;
10511                         // skip transparent surfaces
10512                         texture = surface->texture;
10513                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10514                                 continue;
10515                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10516                                 continue;
10517                         numtriangles = surface->num_triangles;
10518                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10519                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10520                 }
10521         }
10522 }
10523
10524 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10525 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)
10526 {
10527         int renderentityindex;
10528         float worldmins[3];
10529         float worldmaxs[3];
10530         entity_render_t *ent;
10531
10532         if (!cl_decals_newsystem.integer)
10533                 return;
10534
10535         worldmins[0] = worldorigin[0] - worldsize;
10536         worldmins[1] = worldorigin[1] - worldsize;
10537         worldmins[2] = worldorigin[2] - worldsize;
10538         worldmaxs[0] = worldorigin[0] + worldsize;
10539         worldmaxs[1] = worldorigin[1] + worldsize;
10540         worldmaxs[2] = worldorigin[2] + worldsize;
10541
10542         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10543
10544         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10545         {
10546                 ent = r_refdef.scene.entities[renderentityindex];
10547                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10548                         continue;
10549
10550                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10551         }
10552 }
10553
10554 typedef struct r_decalsystem_splatqueue_s
10555 {
10556         vec3_t worldorigin;
10557         vec3_t worldnormal;
10558         float color[4];
10559         float tcrange[4];
10560         float worldsize;
10561         int decalsequence;
10562 }
10563 r_decalsystem_splatqueue_t;
10564
10565 int r_decalsystem_numqueued = 0;
10566 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10567
10568 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)
10569 {
10570         r_decalsystem_splatqueue_t *queue;
10571
10572         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10573                 return;
10574
10575         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10576         VectorCopy(worldorigin, queue->worldorigin);
10577         VectorCopy(worldnormal, queue->worldnormal);
10578         Vector4Set(queue->color, r, g, b, a);
10579         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10580         queue->worldsize = worldsize;
10581         queue->decalsequence = cl.decalsequence++;
10582 }
10583
10584 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10585 {
10586         int i;
10587         r_decalsystem_splatqueue_t *queue;
10588
10589         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10590                 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);
10591         r_decalsystem_numqueued = 0;
10592 }
10593
10594 extern cvar_t cl_decals_max;
10595 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10596 {
10597         int i;
10598         decalsystem_t *decalsystem = &ent->decalsystem;
10599         int numdecals;
10600         int killsequence;
10601         tridecal_t *decal;
10602         float frametime;
10603         float lifetime;
10604
10605         if (!decalsystem->numdecals)
10606                 return;
10607
10608         if (r_showsurfaces.integer)
10609                 return;
10610
10611         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10612         {
10613                 R_DecalSystem_Reset(decalsystem);
10614                 return;
10615         }
10616
10617         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10618         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10619
10620         if (decalsystem->lastupdatetime)
10621                 frametime = (cl.time - decalsystem->lastupdatetime);
10622         else
10623                 frametime = 0;
10624         decalsystem->lastupdatetime = cl.time;
10625         decal = decalsystem->decals;
10626         numdecals = decalsystem->numdecals;
10627
10628         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10629         {
10630                 if (decal->color4f[0][3])
10631                 {
10632                         decal->lived += frametime;
10633                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10634                         {
10635                                 memset(decal, 0, sizeof(*decal));
10636                                 if (decalsystem->freedecal > i)
10637                                         decalsystem->freedecal = i;
10638                         }
10639                 }
10640         }
10641         decal = decalsystem->decals;
10642         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10643                 numdecals--;
10644
10645         // collapse the array by shuffling the tail decals into the gaps
10646         for (;;)
10647         {
10648                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10649                         decalsystem->freedecal++;
10650                 if (decalsystem->freedecal == numdecals)
10651                         break;
10652                 decal[decalsystem->freedecal] = decal[--numdecals];
10653         }
10654
10655         decalsystem->numdecals = numdecals;
10656
10657         if (numdecals <= 0)
10658         {
10659                 // if there are no decals left, reset decalsystem
10660                 R_DecalSystem_Reset(decalsystem);
10661         }
10662 }
10663
10664 extern skinframe_t *decalskinframe;
10665 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10666 {
10667         int i;
10668         decalsystem_t *decalsystem = &ent->decalsystem;
10669         int numdecals;
10670         tridecal_t *decal;
10671         float faderate;
10672         float alpha;
10673         float *v3f;
10674         float *c4f;
10675         float *t2f;
10676         const int *e;
10677         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10678         int numtris = 0;
10679
10680         numdecals = decalsystem->numdecals;
10681         if (!numdecals)
10682                 return;
10683
10684         if (r_showsurfaces.integer)
10685                 return;
10686
10687         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10688         {
10689                 R_DecalSystem_Reset(decalsystem);
10690                 return;
10691         }
10692
10693         // if the model is static it doesn't matter what value we give for
10694         // wantnormals and wanttangents, so this logic uses only rules applicable
10695         // to a model, knowing that they are meaningless otherwise
10696         if (ent == r_refdef.scene.worldentity)
10697                 RSurf_ActiveWorldEntity();
10698         else
10699                 RSurf_ActiveModelEntity(ent, false, false, false);
10700
10701         decalsystem->lastupdatetime = cl.time;
10702         decal = decalsystem->decals;
10703
10704         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10705
10706         // update vertex positions for animated models
10707         v3f = decalsystem->vertex3f;
10708         c4f = decalsystem->color4f;
10709         t2f = decalsystem->texcoord2f;
10710         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10711         {
10712                 if (!decal->color4f[0][3])
10713                         continue;
10714
10715                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10716                         continue;
10717
10718                 // update color values for fading decals
10719                 if (decal->lived >= cl_decals_time.value)
10720                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10721                 else
10722                         alpha = 1.0f;
10723
10724                 c4f[ 0] = decal->color4f[0][0] * alpha;
10725                 c4f[ 1] = decal->color4f[0][1] * alpha;
10726                 c4f[ 2] = decal->color4f[0][2] * alpha;
10727                 c4f[ 3] = 1;
10728                 c4f[ 4] = decal->color4f[1][0] * alpha;
10729                 c4f[ 5] = decal->color4f[1][1] * alpha;
10730                 c4f[ 6] = decal->color4f[1][2] * alpha;
10731                 c4f[ 7] = 1;
10732                 c4f[ 8] = decal->color4f[2][0] * alpha;
10733                 c4f[ 9] = decal->color4f[2][1] * alpha;
10734                 c4f[10] = decal->color4f[2][2] * alpha;
10735                 c4f[11] = 1;
10736
10737                 t2f[0] = decal->texcoord2f[0][0];
10738                 t2f[1] = decal->texcoord2f[0][1];
10739                 t2f[2] = decal->texcoord2f[1][0];
10740                 t2f[3] = decal->texcoord2f[1][1];
10741                 t2f[4] = decal->texcoord2f[2][0];
10742                 t2f[5] = decal->texcoord2f[2][1];
10743
10744                 // update vertex positions for animated models
10745                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10746                 {
10747                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10748                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10749                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10750                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10751                 }
10752                 else
10753                 {
10754                         VectorCopy(decal->vertex3f[0], v3f);
10755                         VectorCopy(decal->vertex3f[1], v3f + 3);
10756                         VectorCopy(decal->vertex3f[2], v3f + 6);
10757                 }
10758
10759                 if (r_refdef.fogenabled)
10760                 {
10761                         alpha = RSurf_FogVertex(v3f);
10762                         VectorScale(c4f, alpha, c4f);
10763                         alpha = RSurf_FogVertex(v3f + 3);
10764                         VectorScale(c4f + 4, alpha, c4f + 4);
10765                         alpha = RSurf_FogVertex(v3f + 6);
10766                         VectorScale(c4f + 8, alpha, c4f + 8);
10767                 }
10768
10769                 v3f += 9;
10770                 c4f += 12;
10771                 t2f += 6;
10772                 numtris++;
10773         }
10774
10775         if (numtris > 0)
10776         {
10777                 r_refdef.stats.drawndecals += numtris;
10778
10779                 // now render the decals all at once
10780                 // (this assumes they all use one particle font texture!)
10781                 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);
10782 //              R_Mesh_ResetTextureState();
10783                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10784                 GL_DepthMask(false);
10785                 GL_DepthRange(0, 1);
10786                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10787                 GL_DepthTest(true);
10788                 GL_CullFace(GL_NONE);
10789                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10790                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10791                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10792         }
10793 }
10794
10795 static void R_DrawModelDecals(void)
10796 {
10797         int i, numdecals;
10798
10799         // fade faster when there are too many decals
10800         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10801         for (i = 0;i < r_refdef.scene.numentities;i++)
10802                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10803
10804         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10805         for (i = 0;i < r_refdef.scene.numentities;i++)
10806                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10807                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10808
10809         R_DecalSystem_ApplySplatEntitiesQueue();
10810
10811         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10812         for (i = 0;i < r_refdef.scene.numentities;i++)
10813                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10814
10815         r_refdef.stats.totaldecals += numdecals;
10816
10817         if (r_showsurfaces.integer)
10818                 return;
10819
10820         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10821
10822         for (i = 0;i < r_refdef.scene.numentities;i++)
10823         {
10824                 if (!r_refdef.viewcache.entityvisible[i])
10825                         continue;
10826                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10827                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10828         }
10829 }
10830
10831 extern cvar_t mod_collision_bih;
10832 void R_DrawDebugModel(void)
10833 {
10834         entity_render_t *ent = rsurface.entity;
10835         int i, j, k, l, flagsmask;
10836         const msurface_t *surface;
10837         dp_model_t *model = ent->model;
10838         vec3_t v;
10839
10840         switch(vid.renderpath)
10841         {
10842         case RENDERPATH_GL11:
10843         case RENDERPATH_GL13:
10844         case RENDERPATH_GL20:
10845                 break;
10846         case RENDERPATH_D3D9:
10847                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10848                 return;
10849         case RENDERPATH_D3D10:
10850                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10851                 return;
10852         case RENDERPATH_D3D11:
10853                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10854                 return;
10855         case RENDERPATH_SOFT:
10856                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10857                 return;
10858         case RENDERPATH_GLES2:
10859                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10860                 return;
10861         }
10862
10863         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10864
10865 //      R_Mesh_ResetTextureState();
10866         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10867         GL_DepthRange(0, 1);
10868         GL_DepthTest(!r_showdisabledepthtest.integer);
10869         GL_DepthMask(false);
10870         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10871
10872         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10873         {
10874                 int triangleindex;
10875                 int bihleafindex;
10876                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10877                 const q3mbrush_t *brush;
10878                 const bih_t *bih = &model->collision_bih;
10879                 const bih_leaf_t *bihleaf;
10880                 float vertex3f[3][3];
10881                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10882                 cullbox = false;
10883                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10884                 {
10885                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10886                                 continue;
10887                         switch (bihleaf->type)
10888                         {
10889                         case BIH_BRUSH:
10890                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10891                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10892                                 {
10893                                         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);
10894                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10895                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10896                                 }
10897                                 break;
10898                         case BIH_COLLISIONTRIANGLE:
10899                                 triangleindex = bihleaf->itemindex;
10900                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10901                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10902                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10903                                 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);
10904                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10905                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10906                                 break;
10907                         case BIH_RENDERTRIANGLE:
10908                                 triangleindex = bihleaf->itemindex;
10909                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10910                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10911                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10912                                 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);
10913                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10914                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10915                                 break;
10916                         }
10917                 }
10918         }
10919
10920         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10921
10922         if (r_showtris.integer || (r_shownormals.value != 0))
10923         {
10924                 if (r_showdisabledepthtest.integer)
10925                 {
10926                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10927                         GL_DepthMask(false);
10928                 }
10929                 else
10930                 {
10931                         GL_BlendFunc(GL_ONE, GL_ZERO);
10932                         GL_DepthMask(true);
10933                 }
10934                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10935                 {
10936                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10937                                 continue;
10938                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10939                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10940                         {
10941                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10942                                 if (r_showtris.value > 0)
10943                                 {
10944                                         if (!rsurface.texture->currentlayers->depthmask)
10945                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10946                                         else if (ent == r_refdef.scene.worldentity)
10947                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10948                                         else
10949                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10950                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10951                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10952                                         RSurf_DrawBatch();
10953                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10954                                         CHECKGLERROR
10955                                 }
10956                                 if (r_shownormals.value < 0)
10957                                 {
10958                                         qglBegin(GL_LINES);
10959                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10960                                         {
10961                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10962                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10963                                                 qglVertex3f(v[0], v[1], v[2]);
10964                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10965                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10966                                                 qglVertex3f(v[0], v[1], v[2]);
10967                                         }
10968                                         qglEnd();
10969                                         CHECKGLERROR
10970                                 }
10971                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10972                                 {
10973                                         qglBegin(GL_LINES);
10974                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10975                                         {
10976                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10977                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10978                                                 qglVertex3f(v[0], v[1], v[2]);
10979                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10980                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10981                                                 qglVertex3f(v[0], v[1], v[2]);
10982                                         }
10983                                         qglEnd();
10984                                         CHECKGLERROR
10985                                         qglBegin(GL_LINES);
10986                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10987                                         {
10988                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10989                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10990                                                 qglVertex3f(v[0], v[1], v[2]);
10991                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10992                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10993                                                 qglVertex3f(v[0], v[1], v[2]);
10994                                         }
10995                                         qglEnd();
10996                                         CHECKGLERROR
10997                                         qglBegin(GL_LINES);
10998                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10999                                         {
11000                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11001                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11002                                                 qglVertex3f(v[0], v[1], v[2]);
11003                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11004                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11005                                                 qglVertex3f(v[0], v[1], v[2]);
11006                                         }
11007                                         qglEnd();
11008                                         CHECKGLERROR
11009                                 }
11010                         }
11011                 }
11012                 rsurface.texture = NULL;
11013         }
11014 }
11015
11016 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11017 int r_maxsurfacelist = 0;
11018 const msurface_t **r_surfacelist = NULL;
11019 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11020 {
11021         int i, j, endj, flagsmask;
11022         dp_model_t *model = r_refdef.scene.worldmodel;
11023         msurface_t *surfaces;
11024         unsigned char *update;
11025         int numsurfacelist = 0;
11026         if (model == NULL)
11027                 return;
11028
11029         if (r_maxsurfacelist < model->num_surfaces)
11030         {
11031                 r_maxsurfacelist = model->num_surfaces;
11032                 if (r_surfacelist)
11033                         Mem_Free((msurface_t**)r_surfacelist);
11034                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11035         }
11036
11037         RSurf_ActiveWorldEntity();
11038
11039         surfaces = model->data_surfaces;
11040         update = model->brushq1.lightmapupdateflags;
11041
11042         // update light styles on this submodel
11043         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11044         {
11045                 model_brush_lightstyleinfo_t *style;
11046                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11047                 {
11048                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11049                         {
11050                                 int *list = style->surfacelist;
11051                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11052                                 for (j = 0;j < style->numsurfaces;j++)
11053                                         update[list[j]] = true;
11054                         }
11055                 }
11056         }
11057
11058         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11059
11060         if (debug)
11061         {
11062                 R_DrawDebugModel();
11063                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11064                 return;
11065         }
11066
11067         rsurface.lightmaptexture = NULL;
11068         rsurface.deluxemaptexture = NULL;
11069         rsurface.uselightmaptexture = false;
11070         rsurface.texture = NULL;
11071         rsurface.rtlight = NULL;
11072         numsurfacelist = 0;
11073         // add visible surfaces to draw list
11074         for (i = 0;i < model->nummodelsurfaces;i++)
11075         {
11076                 j = model->sortedmodelsurfaces[i];
11077                 if (r_refdef.viewcache.world_surfacevisible[j])
11078                         r_surfacelist[numsurfacelist++] = surfaces + j;
11079         }
11080         // update lightmaps if needed
11081         if (model->brushq1.firstrender)
11082         {
11083                 model->brushq1.firstrender = false;
11084                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11085                         if (update[j])
11086                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11087         }
11088         else if (update)
11089         {
11090                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11091                         if (r_refdef.viewcache.world_surfacevisible[j])
11092                                 if (update[j])
11093                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11094         }
11095         // don't do anything if there were no surfaces
11096         if (!numsurfacelist)
11097         {
11098                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11099                 return;
11100         }
11101         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11102
11103         // add to stats if desired
11104         if (r_speeds.integer && !skysurfaces && !depthonly)
11105         {
11106                 r_refdef.stats.world_surfaces += numsurfacelist;
11107                 for (j = 0;j < numsurfacelist;j++)
11108                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11109         }
11110
11111         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11112 }
11113
11114 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11115 {
11116         int i, j, endj, flagsmask;
11117         dp_model_t *model = ent->model;
11118         msurface_t *surfaces;
11119         unsigned char *update;
11120         int numsurfacelist = 0;
11121         if (model == NULL)
11122                 return;
11123
11124         if (r_maxsurfacelist < model->num_surfaces)
11125         {
11126                 r_maxsurfacelist = model->num_surfaces;
11127                 if (r_surfacelist)
11128                         Mem_Free((msurface_t **)r_surfacelist);
11129                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11130         }
11131
11132         // if the model is static it doesn't matter what value we give for
11133         // wantnormals and wanttangents, so this logic uses only rules applicable
11134         // to a model, knowing that they are meaningless otherwise
11135         if (ent == r_refdef.scene.worldentity)
11136                 RSurf_ActiveWorldEntity();
11137         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11138                 RSurf_ActiveModelEntity(ent, false, false, false);
11139         else if (prepass)
11140                 RSurf_ActiveModelEntity(ent, true, true, true);
11141         else if (depthonly)
11142         {
11143                 switch (vid.renderpath)
11144                 {
11145                 case RENDERPATH_GL20:
11146                 case RENDERPATH_D3D9:
11147                 case RENDERPATH_D3D10:
11148                 case RENDERPATH_D3D11:
11149                 case RENDERPATH_SOFT:
11150                 case RENDERPATH_GLES2:
11151                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11152                         break;
11153                 case RENDERPATH_GL13:
11154                 case RENDERPATH_GL11:
11155                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11156                         break;
11157                 }
11158         }
11159         else
11160         {
11161                 switch (vid.renderpath)
11162                 {
11163                 case RENDERPATH_GL20:
11164                 case RENDERPATH_D3D9:
11165                 case RENDERPATH_D3D10:
11166                 case RENDERPATH_D3D11:
11167                 case RENDERPATH_SOFT:
11168                 case RENDERPATH_GLES2:
11169                         RSurf_ActiveModelEntity(ent, true, true, false);
11170                         break;
11171                 case RENDERPATH_GL13:
11172                 case RENDERPATH_GL11:
11173                         RSurf_ActiveModelEntity(ent, true, false, false);
11174                         break;
11175                 }
11176         }
11177
11178         surfaces = model->data_surfaces;
11179         update = model->brushq1.lightmapupdateflags;
11180
11181         // update light styles
11182         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11183         {
11184                 model_brush_lightstyleinfo_t *style;
11185                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11186                 {
11187                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11188                         {
11189                                 int *list = style->surfacelist;
11190                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11191                                 for (j = 0;j < style->numsurfaces;j++)
11192                                         update[list[j]] = true;
11193                         }
11194                 }
11195         }
11196
11197         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11198
11199         if (debug)
11200         {
11201                 R_DrawDebugModel();
11202                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11203                 return;
11204         }
11205
11206         rsurface.lightmaptexture = NULL;
11207         rsurface.deluxemaptexture = NULL;
11208         rsurface.uselightmaptexture = false;
11209         rsurface.texture = NULL;
11210         rsurface.rtlight = NULL;
11211         numsurfacelist = 0;
11212         // add visible surfaces to draw list
11213         for (i = 0;i < model->nummodelsurfaces;i++)
11214                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11215         // don't do anything if there were no surfaces
11216         if (!numsurfacelist)
11217         {
11218                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11219                 return;
11220         }
11221         // update lightmaps if needed
11222         if (update)
11223         {
11224                 int updated = 0;
11225                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11226                 {
11227                         if (update[j])
11228                         {
11229                                 updated++;
11230                                 R_BuildLightMap(ent, surfaces + j);
11231                         }
11232                 }
11233         }
11234         if (update)
11235                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11236                         if (update[j])
11237                                 R_BuildLightMap(ent, surfaces + j);
11238         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11239
11240         // add to stats if desired
11241         if (r_speeds.integer && !skysurfaces && !depthonly)
11242         {
11243                 r_refdef.stats.entities_surfaces += numsurfacelist;
11244                 for (j = 0;j < numsurfacelist;j++)
11245                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11246         }
11247
11248         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11249 }
11250
11251 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11252 {
11253         static texture_t texture;
11254         static msurface_t surface;
11255         const msurface_t *surfacelist = &surface;
11256
11257         // fake enough texture and surface state to render this geometry
11258
11259         texture.update_lastrenderframe = -1; // regenerate this texture
11260         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11261         texture.currentskinframe = skinframe;
11262         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11263         texture.offsetmapping = OFFSETMAPPING_OFF;
11264         texture.offsetscale = 1;
11265         texture.specularscalemod = 1;
11266         texture.specularpowermod = 1;
11267
11268         surface.texture = &texture;
11269         surface.num_triangles = numtriangles;
11270         surface.num_firsttriangle = firsttriangle;
11271         surface.num_vertices = numvertices;
11272         surface.num_firstvertex = firstvertex;
11273
11274         // now render it
11275         rsurface.texture = R_GetCurrentTexture(surface.texture);
11276         rsurface.lightmaptexture = NULL;
11277         rsurface.deluxemaptexture = NULL;
11278         rsurface.uselightmaptexture = false;
11279         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11280 }
11281
11282 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)
11283 {
11284         static msurface_t surface;
11285         const msurface_t *surfacelist = &surface;
11286
11287         // fake enough texture and surface state to render this geometry
11288         surface.texture = texture;
11289         surface.num_triangles = numtriangles;
11290         surface.num_firsttriangle = firsttriangle;
11291         surface.num_vertices = numvertices;
11292         surface.num_firstvertex = firstvertex;
11293
11294         // now render it
11295         rsurface.texture = R_GetCurrentTexture(surface.texture);
11296         rsurface.lightmaptexture = NULL;
11297         rsurface.deluxemaptexture = NULL;
11298         rsurface.uselightmaptexture = false;
11299         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11300 }