]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
a4467e58a57f1809ccbc320602893d7bf9cf214b
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
189
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
206
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 #include "shader_glsl.h"
597 ;
598
599 const char *builtinhlslshaderstring =
600 #include "shader_hlsl.h"
601 ;
602
603 char *glslshaderstring = NULL;
604 char *hlslshaderstring = NULL;
605
606 //=======================================================================================================================================================
607
608 typedef struct shaderpermutationinfo_s
609 {
610         const char *pretext;
611         const char *name;
612 }
613 shaderpermutationinfo_t;
614
615 typedef struct shadermodeinfo_s
616 {
617         const char *vertexfilename;
618         const char *geometryfilename;
619         const char *fragmentfilename;
620         const char *pretext;
621         const char *name;
622 }
623 shadermodeinfo_t;
624
625 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
626 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
627 {
628         {"#define USEDIFFUSE\n", " diffuse"},
629         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
630         {"#define USEVIEWTINT\n", " viewtint"},
631         {"#define USECOLORMAPPING\n", " colormapping"},
632         {"#define USESATURATION\n", " saturation"},
633         {"#define USEFOGINSIDE\n", " foginside"},
634         {"#define USEFOGOUTSIDE\n", " fogoutside"},
635         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
636         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
637         {"#define USEGAMMARAMPS\n", " gammaramps"},
638         {"#define USECUBEFILTER\n", " cubefilter"},
639         {"#define USEGLOW\n", " glow"},
640         {"#define USEBLOOM\n", " bloom"},
641         {"#define USESPECULAR\n", " specular"},
642         {"#define USEPOSTPROCESSING\n", " postprocessing"},
643         {"#define USEREFLECTION\n", " reflection"},
644         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
645         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
646         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
647         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
648         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
649         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
650         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
651         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653         {"#define USEALPHAKILL\n", " alphakill"},
654         {"#define USEREFLECTCUBE\n", " reflectcube"},
655         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656         {"#define USEBOUNCEGRID\n", " bouncegrid"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
678 };
679
680 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
681 {
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
698 };
699
700 struct r_glsl_permutation_s;
701 typedef struct r_glsl_permutation_s
702 {
703         /// hash lookup data
704         struct r_glsl_permutation_s *hashnext;
705         unsigned int mode;
706         unsigned int permutation;
707
708         /// indicates if we have tried compiling this permutation already
709         qboolean compiled;
710         /// 0 if compilation failed
711         int program;
712         // texture units assigned to each detected uniform
713         int tex_Texture_First;
714         int tex_Texture_Second;
715         int tex_Texture_GammaRamps;
716         int tex_Texture_Normal;
717         int tex_Texture_Color;
718         int tex_Texture_Gloss;
719         int tex_Texture_Glow;
720         int tex_Texture_SecondaryNormal;
721         int tex_Texture_SecondaryColor;
722         int tex_Texture_SecondaryGloss;
723         int tex_Texture_SecondaryGlow;
724         int tex_Texture_Pants;
725         int tex_Texture_Shirt;
726         int tex_Texture_FogHeightTexture;
727         int tex_Texture_FogMask;
728         int tex_Texture_Lightmap;
729         int tex_Texture_Deluxemap;
730         int tex_Texture_Attenuation;
731         int tex_Texture_Cube;
732         int tex_Texture_Refraction;
733         int tex_Texture_Reflection;
734         int tex_Texture_ShadowMap2D;
735         int tex_Texture_CubeProjection;
736         int tex_Texture_ScreenDepth;
737         int tex_Texture_ScreenNormalMap;
738         int tex_Texture_ScreenDiffuse;
739         int tex_Texture_ScreenSpecular;
740         int tex_Texture_ReflectMask;
741         int tex_Texture_ReflectCube;
742         int tex_Texture_BounceGrid;
743         /// locations of detected uniforms in program object, or -1 if not found
744         int loc_Texture_First;
745         int loc_Texture_Second;
746         int loc_Texture_GammaRamps;
747         int loc_Texture_Normal;
748         int loc_Texture_Color;
749         int loc_Texture_Gloss;
750         int loc_Texture_Glow;
751         int loc_Texture_SecondaryNormal;
752         int loc_Texture_SecondaryColor;
753         int loc_Texture_SecondaryGloss;
754         int loc_Texture_SecondaryGlow;
755         int loc_Texture_Pants;
756         int loc_Texture_Shirt;
757         int loc_Texture_FogHeightTexture;
758         int loc_Texture_FogMask;
759         int loc_Texture_Lightmap;
760         int loc_Texture_Deluxemap;
761         int loc_Texture_Attenuation;
762         int loc_Texture_Cube;
763         int loc_Texture_Refraction;
764         int loc_Texture_Reflection;
765         int loc_Texture_ShadowMap2D;
766         int loc_Texture_CubeProjection;
767         int loc_Texture_ScreenDepth;
768         int loc_Texture_ScreenNormalMap;
769         int loc_Texture_ScreenDiffuse;
770         int loc_Texture_ScreenSpecular;
771         int loc_Texture_ReflectMask;
772         int loc_Texture_ReflectCube;
773         int loc_Texture_BounceGrid;
774         int loc_Alpha;
775         int loc_BloomBlur_Parameters;
776         int loc_ClientTime;
777         int loc_Color_Ambient;
778         int loc_Color_Diffuse;
779         int loc_Color_Specular;
780         int loc_Color_Glow;
781         int loc_Color_Pants;
782         int loc_Color_Shirt;
783         int loc_DeferredColor_Ambient;
784         int loc_DeferredColor_Diffuse;
785         int loc_DeferredColor_Specular;
786         int loc_DeferredMod_Diffuse;
787         int loc_DeferredMod_Specular;
788         int loc_DistortScaleRefractReflect;
789         int loc_EyePosition;
790         int loc_FogColor;
791         int loc_FogHeightFade;
792         int loc_FogPlane;
793         int loc_FogPlaneViewDist;
794         int loc_FogRangeRecip;
795         int loc_LightColor;
796         int loc_LightDir;
797         int loc_LightPosition;
798         int loc_OffsetMapping_Scale;
799         int loc_PixelSize;
800         int loc_ReflectColor;
801         int loc_ReflectFactor;
802         int loc_ReflectOffset;
803         int loc_RefractColor;
804         int loc_Saturation;
805         int loc_ScreenCenterRefractReflect;
806         int loc_ScreenScaleRefractReflect;
807         int loc_ScreenToDepth;
808         int loc_ShadowMap_Parameters;
809         int loc_ShadowMap_TextureScale;
810         int loc_SpecularPower;
811         int loc_UserVec1;
812         int loc_UserVec2;
813         int loc_UserVec3;
814         int loc_UserVec4;
815         int loc_ViewTintColor;
816         int loc_ViewToLight;
817         int loc_ModelToLight;
818         int loc_TexMatrix;
819         int loc_BackgroundTexMatrix;
820         int loc_ModelViewProjectionMatrix;
821         int loc_ModelViewMatrix;
822         int loc_PixelToScreenTexCoord;
823         int loc_ModelToReflectCube;
824         int loc_ShadowMapMatrix;
825         int loc_BloomColorSubtract;
826         int loc_NormalmapScrollBlend;
827         int loc_BounceGridMatrix;
828         int loc_BounceGridIntensity;
829 }
830 r_glsl_permutation_t;
831
832 #define SHADERPERMUTATION_HASHSIZE 256
833
834
835 // non-degradable "lightweight" shader parameters to keep the permutations simpler
836 // these can NOT degrade! only use for simple stuff
837 enum
838 {
839         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
840         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
841         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
842         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
843         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
844         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
845 };
846 #define SHADERSTATICPARMS_COUNT 6
847
848 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
849 static int shaderstaticparms_count = 0;
850
851 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
852 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
853 qboolean R_CompileShader_CheckStaticParms(void)
854 {
855         static int r_compileshader_staticparms_save[1];
856         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
857         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
858
859         // detect all
860         if (r_glsl_saturation_redcompensate.integer)
861                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
862         if (r_shadow_glossexact.integer)
863                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
864         if (r_glsl_postprocess.integer)
865         {
866                 if (r_glsl_postprocess_uservec1_enable.integer)
867                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
868                 if (r_glsl_postprocess_uservec2_enable.integer)
869                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
870                 if (r_glsl_postprocess_uservec3_enable.integer)
871                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
872                 if (r_glsl_postprocess_uservec4_enable.integer)
873                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
874         }
875         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
876 }
877
878 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
879         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
880                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
881         else \
882                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
883 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
884 {
885         shaderstaticparms_count = 0;
886
887         // emit all
888         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
889         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
890         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
891         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
892         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
893         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
894 }
895
896 /// information about each possible shader permutation
897 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
898 /// currently selected permutation
899 r_glsl_permutation_t *r_glsl_permutation;
900 /// storage for permutations linked in the hash table
901 memexpandablearray_t r_glsl_permutationarray;
902
903 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
904 {
905         //unsigned int hashdepth = 0;
906         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
907         r_glsl_permutation_t *p;
908         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
909         {
910                 if (p->mode == mode && p->permutation == permutation)
911                 {
912                         //if (hashdepth > 10)
913                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
914                         return p;
915                 }
916                 //hashdepth++;
917         }
918         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
919         p->mode = mode;
920         p->permutation = permutation;
921         p->hashnext = r_glsl_permutationhash[mode][hashindex];
922         r_glsl_permutationhash[mode][hashindex] = p;
923         //if (hashdepth > 10)
924         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
925         return p;
926 }
927
928 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
929 {
930         char *shaderstring;
931         if (!filename || !filename[0])
932                 return NULL;
933         if (!strcmp(filename, "glsl/default.glsl"))
934         {
935                 if (!glslshaderstring)
936                 {
937                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
938                         if (glslshaderstring)
939                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
940                         else
941                                 glslshaderstring = (char *)builtinshaderstring;
942                 }
943                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
944                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
945                 return shaderstring;
946         }
947         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948         if (shaderstring)
949         {
950                 if (printfromdisknotice)
951                         Con_DPrintf("from disk %s... ", filename);
952                 return shaderstring;
953         }
954         return shaderstring;
955 }
956
957 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
958 {
959         int i;
960         int sampler;
961         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
962         char *vertexstring, *geometrystring, *fragmentstring;
963         char permutationname[256];
964         int vertstrings_count = 0;
965         int geomstrings_count = 0;
966         int fragstrings_count = 0;
967         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
969         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
970
971         if (p->compiled)
972                 return;
973         p->compiled = true;
974         p->program = 0;
975
976         permutationname[0] = 0;
977         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
978         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
979         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
980
981         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
982
983         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
984         if(vid.support.gl20shaders130)
985         {
986                 vertstrings_list[vertstrings_count++] = "#version 130\n";
987                 geomstrings_list[geomstrings_count++] = "#version 130\n";
988                 fragstrings_list[fragstrings_count++] = "#version 130\n";
989         }
990
991         // the first pretext is which type of shader to compile as
992         // (later these will all be bound together as a program object)
993         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
994         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
995         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
996
997         // the second pretext is the mode (for example a light source)
998         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
999         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1000         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1001         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1002
1003         // now add all the permutation pretexts
1004         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1005         {
1006                 if (permutation & (1<<i))
1007                 {
1008                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1009                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1010                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1011                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1012                 }
1013                 else
1014                 {
1015                         // keep line numbers correct
1016                         vertstrings_list[vertstrings_count++] = "\n";
1017                         geomstrings_list[geomstrings_count++] = "\n";
1018                         fragstrings_list[fragstrings_count++] = "\n";
1019                 }
1020         }
1021
1022         // add static parms
1023         R_CompileShader_AddStaticParms(mode, permutation);
1024         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1025         vertstrings_count += shaderstaticparms_count;
1026         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1027         geomstrings_count += shaderstaticparms_count;
1028         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1029         fragstrings_count += shaderstaticparms_count;
1030
1031         // now append the shader text itself
1032         vertstrings_list[vertstrings_count++] = vertexstring;
1033         geomstrings_list[geomstrings_count++] = geometrystring;
1034         fragstrings_list[fragstrings_count++] = fragmentstring;
1035
1036         // if any sources were NULL, clear the respective list
1037         if (!vertexstring)
1038                 vertstrings_count = 0;
1039         if (!geometrystring)
1040                 geomstrings_count = 0;
1041         if (!fragmentstring)
1042                 fragstrings_count = 0;
1043
1044         // compile the shader program
1045         if (vertstrings_count + geomstrings_count + fragstrings_count)
1046                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1047         if (p->program)
1048         {
1049                 CHECKGLERROR
1050                 qglUseProgram(p->program);CHECKGLERROR
1051                 // look up all the uniform variable names we care about, so we don't
1052                 // have to look them up every time we set them
1053
1054                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1055                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1056                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1057                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1058                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1059                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1060                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1061                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1062                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1063                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1064                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1065                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1066                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1067                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1068                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1069                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1070                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1071                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1072                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1073                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1074                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1075                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1076                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1077                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1078                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1079                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1080                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1081                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1082                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1083                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1084                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1085                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1086                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1087                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1088                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1089                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1090                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1091                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1092                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1093                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1094                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1095                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1096                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1097                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1098                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1099                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1100                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1101                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1102                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1103                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1104                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1105                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1106                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1107                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1108                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1109                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1110                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1111                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1112                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1113                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1114                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1115                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1116                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1117                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1118                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1119                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1120                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1121                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1122                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1123                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1124                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1125                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1126                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1127                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1128                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1129                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1130                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1131                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1132                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1133                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1134                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1135                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1136                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1137                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1138                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1139                 // initialize the samplers to refer to the texture units we use
1140                 p->tex_Texture_First = -1;
1141                 p->tex_Texture_Second = -1;
1142                 p->tex_Texture_GammaRamps = -1;
1143                 p->tex_Texture_Normal = -1;
1144                 p->tex_Texture_Color = -1;
1145                 p->tex_Texture_Gloss = -1;
1146                 p->tex_Texture_Glow = -1;
1147                 p->tex_Texture_SecondaryNormal = -1;
1148                 p->tex_Texture_SecondaryColor = -1;
1149                 p->tex_Texture_SecondaryGloss = -1;
1150                 p->tex_Texture_SecondaryGlow = -1;
1151                 p->tex_Texture_Pants = -1;
1152                 p->tex_Texture_Shirt = -1;
1153                 p->tex_Texture_FogHeightTexture = -1;
1154                 p->tex_Texture_FogMask = -1;
1155                 p->tex_Texture_Lightmap = -1;
1156                 p->tex_Texture_Deluxemap = -1;
1157                 p->tex_Texture_Attenuation = -1;
1158                 p->tex_Texture_Cube = -1;
1159                 p->tex_Texture_Refraction = -1;
1160                 p->tex_Texture_Reflection = -1;
1161                 p->tex_Texture_ShadowMap2D = -1;
1162                 p->tex_Texture_CubeProjection = -1;
1163                 p->tex_Texture_ScreenDepth = -1;
1164                 p->tex_Texture_ScreenNormalMap = -1;
1165                 p->tex_Texture_ScreenDiffuse = -1;
1166                 p->tex_Texture_ScreenSpecular = -1;
1167                 p->tex_Texture_ReflectMask = -1;
1168                 p->tex_Texture_ReflectCube = -1;
1169                 p->tex_Texture_BounceGrid = -1;
1170                 sampler = 0;
1171                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1172                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1173                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1174                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1175                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1176                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1177                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1178                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1179                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1180                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1181                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1182                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1183                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1184                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1185                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1186                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1187                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1188                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1189                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1190                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1191                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1192                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1193                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1194                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1195                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1196                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1197                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1198                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1199                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1200                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1201                 CHECKGLERROR
1202                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1203         }
1204         else
1205                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1206
1207         // free the strings
1208         if (vertexstring)
1209                 Mem_Free(vertexstring);
1210         if (geometrystring)
1211                 Mem_Free(geometrystring);
1212         if (fragmentstring)
1213                 Mem_Free(fragmentstring);
1214 }
1215
1216 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1217 {
1218         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1219         if (r_glsl_permutation != perm)
1220         {
1221                 r_glsl_permutation = perm;
1222                 if (!r_glsl_permutation->program)
1223                 {
1224                         if (!r_glsl_permutation->compiled)
1225                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1226                         if (!r_glsl_permutation->program)
1227                         {
1228                                 // remove features until we find a valid permutation
1229                                 int i;
1230                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1231                                 {
1232                                         // reduce i more quickly whenever it would not remove any bits
1233                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1234                                         if (!(permutation & j))
1235                                                 continue;
1236                                         permutation -= j;
1237                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238                                         if (!r_glsl_permutation->compiled)
1239                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1240                                         if (r_glsl_permutation->program)
1241                                                 break;
1242                                 }
1243                                 if (i >= SHADERPERMUTATION_COUNT)
1244                                 {
1245                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1246                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1247                                         qglUseProgram(0);CHECKGLERROR
1248                                         return; // no bit left to clear, entire mode is broken
1249                                 }
1250                         }
1251                 }
1252                 CHECKGLERROR
1253                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1254         }
1255         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1256         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1257         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1258 }
1259
1260 #ifdef SUPPORTD3D
1261
1262 #ifdef SUPPORTD3D
1263 #include <d3d9.h>
1264 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1265 extern D3DCAPS9 vid_d3d9caps;
1266 #endif
1267
1268 struct r_hlsl_permutation_s;
1269 typedef struct r_hlsl_permutation_s
1270 {
1271         /// hash lookup data
1272         struct r_hlsl_permutation_s *hashnext;
1273         unsigned int mode;
1274         unsigned int permutation;
1275
1276         /// indicates if we have tried compiling this permutation already
1277         qboolean compiled;
1278         /// NULL if compilation failed
1279         IDirect3DVertexShader9 *vertexshader;
1280         IDirect3DPixelShader9 *pixelshader;
1281 }
1282 r_hlsl_permutation_t;
1283
1284 typedef enum D3DVSREGISTER_e
1285 {
1286         D3DVSREGISTER_TexMatrix = 0, // float4x4
1287         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1288         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1289         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1290         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1291         D3DVSREGISTER_ModelToLight = 20, // float4x4
1292         D3DVSREGISTER_EyePosition = 24,
1293         D3DVSREGISTER_FogPlane = 25,
1294         D3DVSREGISTER_LightDir = 26,
1295         D3DVSREGISTER_LightPosition = 27,
1296 }
1297 D3DVSREGISTER_t;
1298
1299 typedef enum D3DPSREGISTER_e
1300 {
1301         D3DPSREGISTER_Alpha = 0,
1302         D3DPSREGISTER_BloomBlur_Parameters = 1,
1303         D3DPSREGISTER_ClientTime = 2,
1304         D3DPSREGISTER_Color_Ambient = 3,
1305         D3DPSREGISTER_Color_Diffuse = 4,
1306         D3DPSREGISTER_Color_Specular = 5,
1307         D3DPSREGISTER_Color_Glow = 6,
1308         D3DPSREGISTER_Color_Pants = 7,
1309         D3DPSREGISTER_Color_Shirt = 8,
1310         D3DPSREGISTER_DeferredColor_Ambient = 9,
1311         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1312         D3DPSREGISTER_DeferredColor_Specular = 11,
1313         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1314         D3DPSREGISTER_DeferredMod_Specular = 13,
1315         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1316         D3DPSREGISTER_EyePosition = 15, // unused
1317         D3DPSREGISTER_FogColor = 16,
1318         D3DPSREGISTER_FogHeightFade = 17,
1319         D3DPSREGISTER_FogPlane = 18,
1320         D3DPSREGISTER_FogPlaneViewDist = 19,
1321         D3DPSREGISTER_FogRangeRecip = 20,
1322         D3DPSREGISTER_LightColor = 21,
1323         D3DPSREGISTER_LightDir = 22, // unused
1324         D3DPSREGISTER_LightPosition = 23,
1325         D3DPSREGISTER_OffsetMapping_Scale = 24,
1326         D3DPSREGISTER_PixelSize = 25,
1327         D3DPSREGISTER_ReflectColor = 26,
1328         D3DPSREGISTER_ReflectFactor = 27,
1329         D3DPSREGISTER_ReflectOffset = 28,
1330         D3DPSREGISTER_RefractColor = 29,
1331         D3DPSREGISTER_Saturation = 30,
1332         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1333         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1334         D3DPSREGISTER_ScreenToDepth = 33,
1335         D3DPSREGISTER_ShadowMap_Parameters = 34,
1336         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1337         D3DPSREGISTER_SpecularPower = 36,
1338         D3DPSREGISTER_UserVec1 = 37,
1339         D3DPSREGISTER_UserVec2 = 38,
1340         D3DPSREGISTER_UserVec3 = 39,
1341         D3DPSREGISTER_UserVec4 = 40,
1342         D3DPSREGISTER_ViewTintColor = 41,
1343         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1344         D3DPSREGISTER_BloomColorSubtract = 43,
1345         D3DPSREGISTER_ViewToLight = 44, // float4x4
1346         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1347         D3DPSREGISTER_NormalmapScrollBlend = 52,
1348         // next at 53
1349 }
1350 D3DPSREGISTER_t;
1351
1352 /// information about each possible shader permutation
1353 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1354 /// currently selected permutation
1355 r_hlsl_permutation_t *r_hlsl_permutation;
1356 /// storage for permutations linked in the hash table
1357 memexpandablearray_t r_hlsl_permutationarray;
1358
1359 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1360 {
1361         //unsigned int hashdepth = 0;
1362         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1363         r_hlsl_permutation_t *p;
1364         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1365         {
1366                 if (p->mode == mode && p->permutation == permutation)
1367                 {
1368                         //if (hashdepth > 10)
1369                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1370                         return p;
1371                 }
1372                 //hashdepth++;
1373         }
1374         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1375         p->mode = mode;
1376         p->permutation = permutation;
1377         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1378         r_hlsl_permutationhash[mode][hashindex] = p;
1379         //if (hashdepth > 10)
1380         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1381         return p;
1382 }
1383
1384 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1385 {
1386         char *shaderstring;
1387         if (!filename || !filename[0])
1388                 return NULL;
1389         if (!strcmp(filename, "hlsl/default.hlsl"))
1390         {
1391                 if (!hlslshaderstring)
1392                 {
1393                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1394                         if (hlslshaderstring)
1395                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1396                         else
1397                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1398                 }
1399                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1400                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1401                 return shaderstring;
1402         }
1403         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1404         if (shaderstring)
1405         {
1406                 if (printfromdisknotice)
1407                         Con_DPrintf("from disk %s... ", filename);
1408                 return shaderstring;
1409         }
1410         return shaderstring;
1411 }
1412
1413 #include <d3dx9.h>
1414 //#include <d3dx9shader.h>
1415 //#include <d3dx9mesh.h>
1416
1417 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1418 {
1419         DWORD *vsbin = NULL;
1420         DWORD *psbin = NULL;
1421         fs_offset_t vsbinsize;
1422         fs_offset_t psbinsize;
1423 //      IDirect3DVertexShader9 *vs = NULL;
1424 //      IDirect3DPixelShader9 *ps = NULL;
1425         ID3DXBuffer *vslog = NULL;
1426         ID3DXBuffer *vsbuffer = NULL;
1427         ID3DXConstantTable *vsconstanttable = NULL;
1428         ID3DXBuffer *pslog = NULL;
1429         ID3DXBuffer *psbuffer = NULL;
1430         ID3DXConstantTable *psconstanttable = NULL;
1431         int vsresult = 0;
1432         int psresult = 0;
1433         char temp[MAX_INPUTLINE];
1434         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1435         qboolean debugshader = gl_paranoid.integer != 0;
1436         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1437         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1438         if (!debugshader)
1439         {
1440                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1441                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1442         }
1443         if ((!vsbin && vertstring) || (!psbin && fragstring))
1444         {
1445                 const char* dllnames_d3dx9 [] =
1446                 {
1447                         "d3dx9_43.dll",
1448                         "d3dx9_42.dll",
1449                         "d3dx9_41.dll",
1450                         "d3dx9_40.dll",
1451                         "d3dx9_39.dll",
1452                         "d3dx9_38.dll",
1453                         "d3dx9_37.dll",
1454                         "d3dx9_36.dll",
1455                         "d3dx9_35.dll",
1456                         "d3dx9_34.dll",
1457                         "d3dx9_33.dll",
1458                         "d3dx9_32.dll",
1459                         "d3dx9_31.dll",
1460                         "d3dx9_30.dll",
1461                         "d3dx9_29.dll",
1462                         "d3dx9_28.dll",
1463                         "d3dx9_27.dll",
1464                         "d3dx9_26.dll",
1465                         "d3dx9_25.dll",
1466                         "d3dx9_24.dll",
1467                         NULL
1468                 };
1469                 dllhandle_t d3dx9_dll = NULL;
1470                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1471                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1472                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1473                 dllfunction_t d3dx9_dllfuncs[] =
1474                 {
1475                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1476                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1477                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1478                         {NULL, NULL}
1479                 };
1480                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1481                 {
1482                         DWORD shaderflags = 0;
1483                         if (debugshader)
1484                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1485                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1486                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1487                         if (vertstring && vertstring[0])
1488                         {
1489                                 if (debugshader)
1490                                 {
1491 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1492 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1493                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1494                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1495                                 }
1496                                 else
1497                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1498                                 if (vsbuffer)
1499                                 {
1500                                         vsbinsize = vsbuffer->GetBufferSize();
1501                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1502                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1503                                         vsbuffer->Release();
1504                                 }
1505                                 if (vslog)
1506                                 {
1507                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1508                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1509                                         vslog->Release();
1510                                 }
1511                         }
1512                         if (fragstring && fragstring[0])
1513                         {
1514                                 if (debugshader)
1515                                 {
1516 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1517 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1518                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1519                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1520                                 }
1521                                 else
1522                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1523                                 if (psbuffer)
1524                                 {
1525                                         psbinsize = psbuffer->GetBufferSize();
1526                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1527                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1528                                         psbuffer->Release();
1529                                 }
1530                                 if (pslog)
1531                                 {
1532                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1533                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1534                                         pslog->Release();
1535                                 }
1536                         }
1537                         Sys_UnloadLibrary(&d3dx9_dll);
1538                 }
1539                 else
1540                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1541         }
1542         if (vsbin && psbin)
1543         {
1544                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1545                 if (FAILED(vsresult))
1546                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1547                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1548                 if (FAILED(psresult))
1549                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1550         }
1551         // free the shader data
1552         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1553         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1554 }
1555
1556 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1557 {
1558         int i;
1559         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1560         int vertstring_length = 0;
1561         int geomstring_length = 0;
1562         int fragstring_length = 0;
1563         char *t;
1564         char *vertexstring, *geometrystring, *fragmentstring;
1565         char *vertstring, *geomstring, *fragstring;
1566         char permutationname[256];
1567         char cachename[256];
1568         int vertstrings_count = 0;
1569         int geomstrings_count = 0;
1570         int fragstrings_count = 0;
1571         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1572         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1573         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1574
1575         if (p->compiled)
1576                 return;
1577         p->compiled = true;
1578         p->vertexshader = NULL;
1579         p->pixelshader = NULL;
1580
1581         permutationname[0] = 0;
1582         cachename[0] = 0;
1583         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1584         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1585         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1586
1587         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1588         strlcat(cachename, "hlsl/", sizeof(cachename));
1589
1590         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1591         vertstrings_count = 0;
1592         geomstrings_count = 0;
1593         fragstrings_count = 0;
1594         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1595         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1596         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1597
1598         // the first pretext is which type of shader to compile as
1599         // (later these will all be bound together as a program object)
1600         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1601         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1602         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1603
1604         // the second pretext is the mode (for example a light source)
1605         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1606         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1607         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1608         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1609         strlcat(cachename, modeinfo->name, sizeof(cachename));
1610
1611         // now add all the permutation pretexts
1612         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1613         {
1614                 if (permutation & (1<<i))
1615                 {
1616                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1617                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1618                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1619                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1620                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1621                 }
1622                 else
1623                 {
1624                         // keep line numbers correct
1625                         vertstrings_list[vertstrings_count++] = "\n";
1626                         geomstrings_list[geomstrings_count++] = "\n";
1627                         fragstrings_list[fragstrings_count++] = "\n";
1628                 }
1629         }
1630
1631         // add static parms
1632         R_CompileShader_AddStaticParms(mode, permutation);
1633         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1634         vertstrings_count += shaderstaticparms_count;
1635         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1636         geomstrings_count += shaderstaticparms_count;
1637         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1638         fragstrings_count += shaderstaticparms_count;
1639
1640         // replace spaces in the cachename with _ characters
1641         for (i = 0;cachename[i];i++)
1642                 if (cachename[i] == ' ')
1643                         cachename[i] = '_';
1644
1645         // now append the shader text itself
1646         vertstrings_list[vertstrings_count++] = vertexstring;
1647         geomstrings_list[geomstrings_count++] = geometrystring;
1648         fragstrings_list[fragstrings_count++] = fragmentstring;
1649
1650         // if any sources were NULL, clear the respective list
1651         if (!vertexstring)
1652                 vertstrings_count = 0;
1653         if (!geometrystring)
1654                 geomstrings_count = 0;
1655         if (!fragmentstring)
1656                 fragstrings_count = 0;
1657
1658         vertstring_length = 0;
1659         for (i = 0;i < vertstrings_count;i++)
1660                 vertstring_length += strlen(vertstrings_list[i]);
1661         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1662         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1663                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1664
1665         geomstring_length = 0;
1666         for (i = 0;i < geomstrings_count;i++)
1667                 geomstring_length += strlen(geomstrings_list[i]);
1668         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1669         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1670                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1671
1672         fragstring_length = 0;
1673         for (i = 0;i < fragstrings_count;i++)
1674                 fragstring_length += strlen(fragstrings_list[i]);
1675         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1676         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1677                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1678
1679         // try to load the cached shader, or generate one
1680         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1681
1682         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1683                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1684         else
1685                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1686
1687         // free the strings
1688         if (vertstring)
1689                 Mem_Free(vertstring);
1690         if (geomstring)
1691                 Mem_Free(geomstring);
1692         if (fragstring)
1693                 Mem_Free(fragstring);
1694         if (vertexstring)
1695                 Mem_Free(vertexstring);
1696         if (geometrystring)
1697                 Mem_Free(geometrystring);
1698         if (fragmentstring)
1699                 Mem_Free(fragmentstring);
1700 }
1701
1702 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1703 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1704 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);}
1705 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);}
1706 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);}
1707 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);}
1708
1709 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1710 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1711 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);}
1712 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);}
1713 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);}
1714 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);}
1715
1716 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1717 {
1718         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1719         if (r_hlsl_permutation != perm)
1720         {
1721                 r_hlsl_permutation = perm;
1722                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1723                 {
1724                         if (!r_hlsl_permutation->compiled)
1725                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1726                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1727                         {
1728                                 // remove features until we find a valid permutation
1729                                 int i;
1730                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1731                                 {
1732                                         // reduce i more quickly whenever it would not remove any bits
1733                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1734                                         if (!(permutation & j))
1735                                                 continue;
1736                                         permutation -= j;
1737                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738                                         if (!r_hlsl_permutation->compiled)
1739                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1740                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1741                                                 break;
1742                                 }
1743                                 if (i >= SHADERPERMUTATION_COUNT)
1744                                 {
1745                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1746                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1747                                         return; // no bit left to clear, entire mode is broken
1748                                 }
1749                         }
1750                 }
1751                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1752                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1753         }
1754         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1755         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1756         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1757 }
1758 #endif
1759
1760 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1761 {
1762         DPSOFTRAST_SetShader(mode, permutation);
1763         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1764         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1765         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1766 }
1767
1768 void R_GLSL_Restart_f(void)
1769 {
1770         unsigned int i, limit;
1771         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1772                 Mem_Free(glslshaderstring);
1773         glslshaderstring = NULL;
1774         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1775                 Mem_Free(hlslshaderstring);
1776         hlslshaderstring = NULL;
1777         switch(vid.renderpath)
1778         {
1779         case RENDERPATH_D3D9:
1780 #ifdef SUPPORTD3D
1781                 {
1782                         r_hlsl_permutation_t *p;
1783                         r_hlsl_permutation = NULL;
1784                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1785                         for (i = 0;i < limit;i++)
1786                         {
1787                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1788                                 {
1789                                         if (p->vertexshader)
1790                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1791                                         if (p->pixelshader)
1792                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1793                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1794                                 }
1795                         }
1796                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1797                 }
1798 #endif
1799                 break;
1800         case RENDERPATH_D3D10:
1801                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1802                 break;
1803         case RENDERPATH_D3D11:
1804                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1805                 break;
1806         case RENDERPATH_GL20:
1807         case RENDERPATH_GLES2:
1808                 {
1809                         r_glsl_permutation_t *p;
1810                         r_glsl_permutation = NULL;
1811                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1812                         for (i = 0;i < limit;i++)
1813                         {
1814                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1815                                 {
1816                                         GL_Backend_FreeProgram(p->program);
1817                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1818                                 }
1819                         }
1820                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1821                 }
1822                 break;
1823         case RENDERPATH_GL13:
1824         case RENDERPATH_GL11:
1825                 break;
1826         case RENDERPATH_SOFT:
1827                 break;
1828         }
1829 }
1830
1831 void R_GLSL_DumpShader_f(void)
1832 {
1833         int i;
1834         qfile_t *file;
1835
1836         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1837         if (file)
1838         {
1839                 FS_Print(file, "/* The engine may define the following macros:\n");
1840                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1841                 for (i = 0;i < SHADERMODE_COUNT;i++)
1842                         FS_Print(file, glslshadermodeinfo[i].pretext);
1843                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1844                         FS_Print(file, shaderpermutationinfo[i].pretext);
1845                 FS_Print(file, "*/\n");
1846                 FS_Print(file, builtinshaderstring);
1847                 FS_Close(file);
1848                 Con_Printf("glsl/default.glsl written\n");
1849         }
1850         else
1851                 Con_Printf("failed to write to glsl/default.glsl\n");
1852
1853         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1854         if (file)
1855         {
1856                 FS_Print(file, "/* The engine may define the following macros:\n");
1857                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1858                 for (i = 0;i < SHADERMODE_COUNT;i++)
1859                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1860                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1861                         FS_Print(file, shaderpermutationinfo[i].pretext);
1862                 FS_Print(file, "*/\n");
1863                 FS_Print(file, builtinhlslshaderstring);
1864                 FS_Close(file);
1865                 Con_Printf("hlsl/default.hlsl written\n");
1866         }
1867         else
1868                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1869 }
1870
1871 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1872 {
1873         if (!second)
1874                 texturemode = GL_MODULATE;
1875         switch (vid.renderpath)
1876         {
1877         case RENDERPATH_D3D9:
1878 #ifdef SUPPORTD3D
1879                 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))));
1880                 R_Mesh_TexBind(GL20TU_FIRST , first );
1881                 R_Mesh_TexBind(GL20TU_SECOND, second);
1882 #endif
1883                 break;
1884         case RENDERPATH_D3D10:
1885                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1886                 break;
1887         case RENDERPATH_D3D11:
1888                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889                 break;
1890         case RENDERPATH_GL20:
1891         case RENDERPATH_GLES2:
1892                 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))));
1893                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1894                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1895                 break;
1896         case RENDERPATH_GL13:
1897                 R_Mesh_TexBind(0, first );
1898                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1899                 R_Mesh_TexBind(1, second);
1900                 if (second)
1901                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1902                 break;
1903         case RENDERPATH_GL11:
1904                 R_Mesh_TexBind(0, first );
1905                 break;
1906         case RENDERPATH_SOFT:
1907                 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))));
1908                 R_Mesh_TexBind(GL20TU_FIRST , first );
1909                 R_Mesh_TexBind(GL20TU_SECOND, second);
1910                 break;
1911         }
1912 }
1913
1914 void R_SetupShader_DepthOrShadow(void)
1915 {
1916         switch (vid.renderpath)
1917         {
1918         case RENDERPATH_D3D9:
1919 #ifdef SUPPORTD3D
1920                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1921 #endif
1922                 break;
1923         case RENDERPATH_D3D10:
1924                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925                 break;
1926         case RENDERPATH_D3D11:
1927                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_GL20:
1930         case RENDERPATH_GLES2:
1931                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1932                 break;
1933         case RENDERPATH_GL13:
1934                 R_Mesh_TexBind(0, 0);
1935                 R_Mesh_TexBind(1, 0);
1936                 break;
1937         case RENDERPATH_GL11:
1938                 R_Mesh_TexBind(0, 0);
1939                 break;
1940         case RENDERPATH_SOFT:
1941                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1942                 break;
1943         }
1944 }
1945
1946 void R_SetupShader_ShowDepth(void)
1947 {
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTHLSL
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1964                 break;
1965         case RENDERPATH_GL13:
1966                 break;
1967         case RENDERPATH_GL11:
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1971                 break;
1972         }
1973 }
1974
1975 extern qboolean r_shadow_usingdeferredprepass;
1976 extern cvar_t r_shadow_deferred_8bitrange;
1977 extern rtexture_t *r_shadow_attenuationgradienttexture;
1978 extern rtexture_t *r_shadow_attenuation2dtexture;
1979 extern rtexture_t *r_shadow_attenuation3dtexture;
1980 extern qboolean r_shadow_usingshadowmap2d;
1981 extern qboolean r_shadow_usingshadowmaportho;
1982 extern float r_shadow_shadowmap_texturescale[2];
1983 extern float r_shadow_shadowmap_parameters[4];
1984 extern qboolean r_shadow_shadowmapvsdct;
1985 extern qboolean r_shadow_shadowmapsampler;
1986 extern int r_shadow_shadowmappcf;
1987 extern rtexture_t *r_shadow_shadowmap2dtexture;
1988 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1989 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1990 extern matrix4x4_t r_shadow_shadowmapmatrix;
1991 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1992 extern int r_shadow_prepass_width;
1993 extern int r_shadow_prepass_height;
1994 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1995 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1996 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1997 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1998 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1999
2000 #define BLENDFUNC_ALLOWS_COLORMOD      1
2001 #define BLENDFUNC_ALLOWS_FOG           2
2002 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2003 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2004 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2005 static int R_BlendFuncFlags(int src, int dst)
2006 {
2007         int r = 0;
2008
2009         // a blendfunc allows colormod if:
2010         // a) it can never keep the destination pixel invariant, or
2011         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2012         // this is to prevent unintended side effects from colormod
2013
2014         // a blendfunc allows fog if:
2015         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2016         // this is to prevent unintended side effects from fog
2017
2018         // these checks are the output of fogeval.pl
2019
2020         r |= BLENDFUNC_ALLOWS_COLORMOD;
2021         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2022         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2023         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2024         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2025         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2026         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2028         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2029         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2030         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2031         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2032         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2033         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2034         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2036         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2037         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2038         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2039         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2040         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2041         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2042
2043         return r;
2044 }
2045
2046 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)
2047 {
2048         // select a permutation of the lighting shader appropriate to this
2049         // combination of texture, entity, light source, and fogging, only use the
2050         // minimum features necessary to avoid wasting rendering time in the
2051         // fragment shader on features that are not being used
2052         unsigned int permutation = 0;
2053         unsigned int mode = 0;
2054         int blendfuncflags;
2055         static float dummy_colormod[3] = {1, 1, 1};
2056         float *colormod = rsurface.colormod;
2057         float m16f[16];
2058         matrix4x4_t tempmatrix;
2059         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2060         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2061                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2062         if (rsurfacepass == RSURFPASS_BACKGROUND)
2063         {
2064                 // distorted background
2065                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2066                 {
2067                         mode = SHADERMODE_WATER;
2068                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2069                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2070                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2071                         {
2072                                 // this is the right thing to do for wateralpha
2073                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2074                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2075                         }
2076                         else
2077                         {
2078                                 // this is the right thing to do for entity alpha
2079                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2080                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2081                         }
2082                 }
2083                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2084                 {
2085                         mode = SHADERMODE_REFRACTION;
2086                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2087                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2088                 }
2089                 else
2090                 {
2091                         mode = SHADERMODE_GENERIC;
2092                         permutation |= SHADERPERMUTATION_DIFFUSE;
2093                         GL_BlendFunc(GL_ONE, GL_ZERO);
2094                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2095                 }
2096         }
2097         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2098         {
2099                 if (r_glsl_offsetmapping.integer)
2100                 {
2101                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2102                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2103                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2104                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2105                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2106                         {
2107                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2108                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2109                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2110                         }
2111                 }
2112                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2113                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2114                 // normalmap (deferred prepass), may use alpha test on diffuse
2115                 mode = SHADERMODE_DEFERREDGEOMETRY;
2116                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2117                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2118                 GL_BlendFunc(GL_ONE, GL_ZERO);
2119                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2120         }
2121         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2122         {
2123                 if (r_glsl_offsetmapping.integer)
2124                 {
2125                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2126                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2127                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2128                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2129                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2130                         {
2131                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2133                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2134                         }
2135                 }
2136                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2137                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2138                 // light source
2139                 mode = SHADERMODE_LIGHTSOURCE;
2140                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2141                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2142                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2143                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2144                 if (diffusescale > 0)
2145                         permutation |= SHADERPERMUTATION_DIFFUSE;
2146                 if (specularscale > 0)
2147                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2148                 if (r_refdef.fogenabled)
2149                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2150                 if (rsurface.texture->colormapping)
2151                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2152                 if (r_shadow_usingshadowmap2d)
2153                 {
2154                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2155                         if(r_shadow_shadowmapvsdct)
2156                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2157
2158                         if (r_shadow_shadowmapsampler)
2159                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2160                         if (r_shadow_shadowmappcf > 1)
2161                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2162                         else if (r_shadow_shadowmappcf)
2163                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2164                 }
2165                 if (rsurface.texture->reflectmasktexture)
2166                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2167                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2168                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2169         }
2170         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2171         {
2172                 if (r_glsl_offsetmapping.integer)
2173                 {
2174                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2175                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2176                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2177                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2178                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2179                         {
2180                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2181                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2182                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2183                         }
2184                 }
2185                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2186                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2187                 // unshaded geometry (fullbright or ambient model lighting)
2188                 mode = SHADERMODE_FLATCOLOR;
2189                 ambientscale = diffusescale = specularscale = 0;
2190                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2191                         permutation |= SHADERPERMUTATION_GLOW;
2192                 if (r_refdef.fogenabled)
2193                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2194                 if (rsurface.texture->colormapping)
2195                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2196                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2197                 {
2198                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2199                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2200
2201                         if (r_shadow_shadowmapsampler)
2202                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2203                         if (r_shadow_shadowmappcf > 1)
2204                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2205                         else if (r_shadow_shadowmappcf)
2206                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2207                 }
2208                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2209                         permutation |= SHADERPERMUTATION_REFLECTION;
2210                 if (rsurface.texture->reflectmasktexture)
2211                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2212                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2213                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2214         }
2215         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2216         {
2217                 if (r_glsl_offsetmapping.integer)
2218                 {
2219                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2220                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2221                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2222                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2223                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2224                         {
2225                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2226                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2227                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2228                         }
2229                 }
2230                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2231                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2232                 // directional model lighting
2233                 mode = SHADERMODE_LIGHTDIRECTION;
2234                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2235                         permutation |= SHADERPERMUTATION_GLOW;
2236                 permutation |= SHADERPERMUTATION_DIFFUSE;
2237                 if (specularscale > 0)
2238                         permutation |= SHADERPERMUTATION_SPECULAR;
2239                 if (r_refdef.fogenabled)
2240                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2241                 if (rsurface.texture->colormapping)
2242                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2243                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2244                 {
2245                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2246                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2247
2248                         if (r_shadow_shadowmapsampler)
2249                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2250                         if (r_shadow_shadowmappcf > 1)
2251                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2252                         else if (r_shadow_shadowmappcf)
2253                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2254                 }
2255                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2256                         permutation |= SHADERPERMUTATION_REFLECTION;
2257                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2258                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2259                 if (rsurface.texture->reflectmasktexture)
2260                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2261                 if (r_shadow_bouncegridtexture)
2262                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2263                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265         }
2266         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2267         {
2268                 if (r_glsl_offsetmapping.integer)
2269                 {
2270                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2271                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2272                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2273                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2274                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2275                         {
2276                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2277                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2278                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2279                         }
2280                 }
2281                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2282                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2283                 // ambient model lighting
2284                 mode = SHADERMODE_LIGHTDIRECTION;
2285                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2286                         permutation |= SHADERPERMUTATION_GLOW;
2287                 if (r_refdef.fogenabled)
2288                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289                 if (rsurface.texture->colormapping)
2290                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2291                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2292                 {
2293                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2294                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2295
2296                         if (r_shadow_shadowmapsampler)
2297                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2298                         if (r_shadow_shadowmappcf > 1)
2299                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2300                         else if (r_shadow_shadowmappcf)
2301                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2302                 }
2303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2304                         permutation |= SHADERPERMUTATION_REFLECTION;
2305                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2306                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2307                 if (rsurface.texture->reflectmasktexture)
2308                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2309                 if (r_shadow_bouncegridtexture)
2310                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2311                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2313         }
2314         else
2315         {
2316                 if (r_glsl_offsetmapping.integer)
2317                 {
2318                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2319                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2320                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2321                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2322                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2323                         {
2324                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2325                                 if (r_glsl_offsetmapping_reliefmapping.integer)
2326                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2327                         }
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2330                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2331                 // lightmapped wall
2332                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2333                         permutation |= SHADERPERMUTATION_GLOW;
2334                 if (r_refdef.fogenabled)
2335                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2336                 if (rsurface.texture->colormapping)
2337                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2338                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2339                 {
2340                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2341                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2342
2343                         if (r_shadow_shadowmapsampler)
2344                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2345                         if (r_shadow_shadowmappcf > 1)
2346                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2347                         else if (r_shadow_shadowmappcf)
2348                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2349                 }
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2351                         permutation |= SHADERPERMUTATION_REFLECTION;
2352                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2353                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2354                 if (rsurface.texture->reflectmasktexture)
2355                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2356                 if (FAKELIGHT_ENABLED)
2357                 {
2358                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2359                         mode = SHADERMODE_FAKELIGHT;
2360                         permutation |= SHADERPERMUTATION_DIFFUSE;
2361                         if (specularscale > 0)
2362                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2363                 }
2364                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2365                 {
2366                         // deluxemapping (light direction texture)
2367                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2368                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2369                         else
2370                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2371                         permutation |= SHADERPERMUTATION_DIFFUSE;
2372                         if (specularscale > 0)
2373                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2374                 }
2375                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2376                 {
2377                         // fake deluxemapping (uniform light direction in tangentspace)
2378                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2379                         permutation |= SHADERPERMUTATION_DIFFUSE;
2380                         if (specularscale > 0)
2381                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2382                 }
2383                 else if (rsurface.uselightmaptexture)
2384                 {
2385                         // ordinary lightmapping (q1bsp, q3bsp)
2386                         mode = SHADERMODE_LIGHTMAP;
2387                 }
2388                 else
2389                 {
2390                         // ordinary vertex coloring (q3bsp)
2391                         mode = SHADERMODE_VERTEXCOLOR;
2392                 }
2393                 if (r_shadow_bouncegridtexture)
2394                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2395                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397         }
2398         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2399                 colormod = dummy_colormod;
2400         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2401                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2402         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2403                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2404         switch(vid.renderpath)
2405         {
2406         case RENDERPATH_D3D9:
2407 #ifdef SUPPORTD3D
2408                 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);
2409                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2410                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2411                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2412                 if (mode == SHADERMODE_LIGHTSOURCE)
2413                 {
2414                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2415                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2416                 }
2417                 else
2418                 {
2419                         if (mode == SHADERMODE_LIGHTDIRECTION)
2420                         {
2421                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2422                         }
2423                 }
2424                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2425                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2426                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2427                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2428                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2429
2430                 if (mode == SHADERMODE_LIGHTSOURCE)
2431                 {
2432                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2433                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2434                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2435                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2436                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2437
2438                         // additive passes are only darkened by fog, not tinted
2439                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2440                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2441                 }
2442                 else
2443                 {
2444                         if (mode == SHADERMODE_FLATCOLOR)
2445                         {
2446                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2447                         }
2448                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2449                         {
2450                                 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]);
2451                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2452                                 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);
2453                                 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);
2454                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2455                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2456                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2457                         }
2458                         else
2459                         {
2460                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2461                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2462                                 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);
2463                                 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);
2464                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2465                         }
2466                         // additive passes are only darkened by fog, not tinted
2467                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2468                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2469                         else
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2471                         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);
2472                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2473                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2474                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2475                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2476                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2477                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2478                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2479                         if (mode == SHADERMODE_WATER)
2480                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2481                 }
2482                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2483                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2484                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2485                 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));
2486                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2487                 if (rsurface.texture->pantstexture)
2488                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2489                 else
2490                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2491                 if (rsurface.texture->shirttexture)
2492                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2493                 else
2494                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2495                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2496                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2497                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2498                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2499                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2500                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2501                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2502
2503                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2504                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2505                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2506                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2507                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2508                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2509                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2510                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2511                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2512                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2513                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2514                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2515                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2516                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2517                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2518                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2519                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2520                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2521                 {
2522                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2523                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2524                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2525                 }
2526                 else
2527                 {
2528                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2529                 }
2530 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2531 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2532                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2533                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2534                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2535                 {
2536                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2537                         if (rsurface.rtlight)
2538                         {
2539                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2540                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2541                         }
2542                 }
2543 #endif
2544                 break;
2545         case RENDERPATH_D3D10:
2546                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2547                 break;
2548         case RENDERPATH_D3D11:
2549                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2550                 break;
2551         case RENDERPATH_GL20:
2552         case RENDERPATH_GLES2:
2553                 if (!vid.useinterleavedarrays)
2554                 {
2555                         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);
2556                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2557                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2558                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2559                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2560                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2561                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2562                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2563                 }
2564                 else
2565                 {
2566                         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);
2567                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2568                 }
2569                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2570                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2571                 if (mode == SHADERMODE_LIGHTSOURCE)
2572                 {
2573                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2574                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2575                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2576                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2577                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2578                         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);
2579         
2580                         // additive passes are only darkened by fog, not tinted
2581                         if (r_glsl_permutation->loc_FogColor >= 0)
2582                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2583                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2584                 }
2585                 else
2586                 {
2587                         if (mode == SHADERMODE_FLATCOLOR)
2588                         {
2589                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2590                         }
2591                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2592                         {
2593                                 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]);
2594                                 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]);
2595                                 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);
2596                                 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);
2597                                 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);
2598                                 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]);
2599                                 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]);
2600                         }
2601                         else
2602                         {
2603                                 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]);
2604                                 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]);
2605                                 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);
2606                                 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);
2607                                 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);
2608                         }
2609                         // additive passes are only darkened by fog, not tinted
2610                         if (r_glsl_permutation->loc_FogColor >= 0)
2611                         {
2612                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2613                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2614                                 else
2615                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2616                         }
2617                         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);
2618                         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]);
2619                         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]);
2620                         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]);
2621                         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]);
2622                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2623                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2624                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2625                         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]);
2626                 }
2627                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2628                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2629                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2630                 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]);
2631                 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]);
2632
2633                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2634                 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));
2635                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2636                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2637                 {
2638                         if (rsurface.texture->pantstexture)
2639                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2640                         else
2641                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2642                 }
2643                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2644                 {
2645                         if (rsurface.texture->shirttexture)
2646                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2647                         else
2648                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2649                 }
2650                 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]);
2651                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2652                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2653                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2654                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2655                 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]);
2656                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2657                 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);}
2658                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2659
2660                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2661                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2662                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2663                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2664                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2665                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2666                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2667                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2668                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2669                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2670                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2671                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2672                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2673                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2674                 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);
2675                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2676                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2677                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2678                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2679                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2680                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2681                 {
2682                         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);
2683                         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);
2684                         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);
2685                 }
2686                 else
2687                 {
2688                         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);
2689                 }
2690                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2691                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2692                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2693                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2694                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2695                 {
2696                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2697                         if (rsurface.rtlight)
2698                         {
2699                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2700                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2701                         }
2702                 }
2703                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2704                 CHECKGLERROR
2705                 break;
2706         case RENDERPATH_GL13:
2707         case RENDERPATH_GL11:
2708                 break;
2709         case RENDERPATH_SOFT:
2710                 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);
2711                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2712                 R_SetupShader_SetPermutationSoft(mode, permutation);
2713                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2714                 if (mode == SHADERMODE_LIGHTSOURCE)
2715                 {
2716                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2717                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2718                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2719                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2720                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2721                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2722         
2723                         // additive passes are only darkened by fog, not tinted
2724                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2725                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2726                 }
2727                 else
2728                 {
2729                         if (mode == SHADERMODE_FLATCOLOR)
2730                         {
2731                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2732                         }
2733                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2734                         {
2735                                 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]);
2736                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2737                                 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);
2738                                 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);
2739                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2740                                 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]);
2741                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2742                         }
2743                         else
2744                         {
2745                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2746                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2747                                 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);
2748                                 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);
2749                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2750                         }
2751                         // additive passes are only darkened by fog, not tinted
2752                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2753                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2754                         else
2755                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2756                         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);
2757                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2758                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2759                         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]);
2760                         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]);
2761                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2762                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2763                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2764                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2765                 }
2766                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2767                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2768                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2769                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2770                 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]);
2771
2772                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2773                 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));
2774                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2775                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2776                 {
2777                         if (rsurface.texture->pantstexture)
2778                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2779                         else
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2781                 }
2782                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2783                 {
2784                         if (rsurface.texture->shirttexture)
2785                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2786                         else
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2788                 }
2789                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2790                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2791                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2792                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2793                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2794                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2795                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2796
2797                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2798                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2799                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2800                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2801                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2802                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2803                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2804                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2805                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2806                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2807                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2808                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2809                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2810                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2811                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2812                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2813                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2814                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2815                 {
2816                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2817                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2818                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2819                 }
2820                 else
2821                 {
2822                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2823                 }
2824 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2825 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2826                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2827                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2828                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2829                 {
2830                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2831                         if (rsurface.rtlight)
2832                         {
2833                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2834                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2835                         }
2836                 }
2837                 break;
2838         }
2839 }
2840
2841 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2842 {
2843         // select a permutation of the lighting shader appropriate to this
2844         // combination of texture, entity, light source, and fogging, only use the
2845         // minimum features necessary to avoid wasting rendering time in the
2846         // fragment shader on features that are not being used
2847         unsigned int permutation = 0;
2848         unsigned int mode = 0;
2849         const float *lightcolorbase = rtlight->currentcolor;
2850         float ambientscale = rtlight->ambientscale;
2851         float diffusescale = rtlight->diffusescale;
2852         float specularscale = rtlight->specularscale;
2853         // this is the location of the light in view space
2854         vec3_t viewlightorigin;
2855         // this transforms from view space (camera) to light space (cubemap)
2856         matrix4x4_t viewtolight;
2857         matrix4x4_t lighttoview;
2858         float viewtolight16f[16];
2859         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2860         // light source
2861         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2862         if (rtlight->currentcubemap != r_texture_whitecube)
2863                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2864         if (diffusescale > 0)
2865                 permutation |= SHADERPERMUTATION_DIFFUSE;
2866         if (specularscale > 0)
2867                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2868         if (r_shadow_usingshadowmap2d)
2869         {
2870                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2871                 if (r_shadow_shadowmapvsdct)
2872                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2873
2874                 if (r_shadow_shadowmapsampler)
2875                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2876                 if (r_shadow_shadowmappcf > 1)
2877                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2878                 else if (r_shadow_shadowmappcf)
2879                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2880         }
2881         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2882         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2883         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2884         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2885         switch(vid.renderpath)
2886         {
2887         case RENDERPATH_D3D9:
2888 #ifdef SUPPORTD3D
2889                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2890                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2891                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2892                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2893                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2894                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2895                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2896                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2897                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2898                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2899                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2900
2901                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2902                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2903                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2904                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2905                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2906                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2907 #endif
2908                 break;
2909         case RENDERPATH_D3D10:
2910                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2911                 break;
2912         case RENDERPATH_D3D11:
2913                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2914                 break;
2915         case RENDERPATH_GL20:
2916         case RENDERPATH_GLES2:
2917                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2918                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2919                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2920                 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);
2921                 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);
2922                 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);
2923                 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]);
2924                 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]);
2925                 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));
2926                 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]);
2927                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2928
2929                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2930                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2931                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2932                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2933                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2934                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2935                 break;
2936         case RENDERPATH_GL13:
2937         case RENDERPATH_GL11:
2938                 break;
2939         case RENDERPATH_SOFT:
2940                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2941                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2942                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2943                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2944                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2945                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2946                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2947                 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]);
2948                 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));
2949                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2950                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2951
2952                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2953                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2954                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2955                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2956                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2957                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2958                 break;
2959         }
2960 }
2961
2962 #define SKINFRAME_HASH 1024
2963
2964 typedef struct
2965 {
2966         int loadsequence; // incremented each level change
2967         memexpandablearray_t array;
2968         skinframe_t *hash[SKINFRAME_HASH];
2969 }
2970 r_skinframe_t;
2971 r_skinframe_t r_skinframe;
2972
2973 void R_SkinFrame_PrepareForPurge(void)
2974 {
2975         r_skinframe.loadsequence++;
2976         // wrap it without hitting zero
2977         if (r_skinframe.loadsequence >= 200)
2978                 r_skinframe.loadsequence = 1;
2979 }
2980
2981 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2982 {
2983         if (!skinframe)
2984                 return;
2985         // mark the skinframe as used for the purging code
2986         skinframe->loadsequence = r_skinframe.loadsequence;
2987 }
2988
2989 void R_SkinFrame_Purge(void)
2990 {
2991         int i;
2992         skinframe_t *s;
2993         for (i = 0;i < SKINFRAME_HASH;i++)
2994         {
2995                 for (s = r_skinframe.hash[i];s;s = s->next)
2996                 {
2997                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2998                         {
2999                                 if (s->merged == s->base)
3000                                         s->merged = NULL;
3001                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3002                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3003                                 R_PurgeTexture(s->merged);s->merged = NULL;
3004                                 R_PurgeTexture(s->base  );s->base   = NULL;
3005                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3006                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3007                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3008                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3009                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3010                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3011                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3012                                 s->loadsequence = 0;
3013                         }
3014                 }
3015         }
3016 }
3017
3018 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3019         skinframe_t *item;
3020         char basename[MAX_QPATH];
3021
3022         Image_StripImageExtension(name, basename, sizeof(basename));
3023
3024         if( last == NULL ) {
3025                 int hashindex;
3026                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3027                 item = r_skinframe.hash[hashindex];
3028         } else {
3029                 item = last->next;
3030         }
3031
3032         // linearly search through the hash bucket
3033         for( ; item ; item = item->next ) {
3034                 if( !strcmp( item->basename, basename ) ) {
3035                         return item;
3036                 }
3037         }
3038         return NULL;
3039 }
3040
3041 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3042 {
3043         skinframe_t *item;
3044         int hashindex;
3045         char basename[MAX_QPATH];
3046
3047         Image_StripImageExtension(name, basename, sizeof(basename));
3048
3049         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3050         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3051                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3052                         break;
3053
3054         if (!item) {
3055                 rtexture_t *dyntexture;
3056                 // check whether its a dynamic texture
3057                 dyntexture = CL_GetDynTexture( basename );
3058                 if (!add && !dyntexture)
3059                         return NULL;
3060                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3061                 memset(item, 0, sizeof(*item));
3062                 strlcpy(item->basename, basename, sizeof(item->basename));
3063                 item->base = dyntexture; // either NULL or dyntexture handle
3064                 item->textureflags = textureflags;
3065                 item->comparewidth = comparewidth;
3066                 item->compareheight = compareheight;
3067                 item->comparecrc = comparecrc;
3068                 item->next = r_skinframe.hash[hashindex];
3069                 r_skinframe.hash[hashindex] = item;
3070         }
3071         else if( item->base == NULL )
3072         {
3073                 rtexture_t *dyntexture;
3074                 // check whether its a dynamic texture
3075                 // 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]
3076                 dyntexture = CL_GetDynTexture( basename );
3077                 item->base = dyntexture; // either NULL or dyntexture handle
3078         }
3079
3080         R_SkinFrame_MarkUsed(item);
3081         return item;
3082 }
3083
3084 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3085         { \
3086                 unsigned long long avgcolor[5], wsum; \
3087                 int pix, comp, w; \
3088                 avgcolor[0] = 0; \
3089                 avgcolor[1] = 0; \
3090                 avgcolor[2] = 0; \
3091                 avgcolor[3] = 0; \
3092                 avgcolor[4] = 0; \
3093                 wsum = 0; \
3094                 for(pix = 0; pix < cnt; ++pix) \
3095                 { \
3096                         w = 0; \
3097                         for(comp = 0; comp < 3; ++comp) \
3098                                 w += getpixel; \
3099                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3100                         { \
3101                                 ++wsum; \
3102                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3103                                 w = getpixel; \
3104                                 for(comp = 0; comp < 3; ++comp) \
3105                                         avgcolor[comp] += getpixel * w; \
3106                                 avgcolor[3] += w; \
3107                         } \
3108                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3109                         avgcolor[4] += getpixel; \
3110                 } \
3111                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3112                         avgcolor[3] = 1; \
3113                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3114                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3115                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3116                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3117         }
3118
3119 extern cvar_t gl_picmip;
3120 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3121 {
3122         int j;
3123         unsigned char *pixels;
3124         unsigned char *bumppixels;
3125         unsigned char *basepixels = NULL;
3126         int basepixels_width = 0;
3127         int basepixels_height = 0;
3128         skinframe_t *skinframe;
3129         rtexture_t *ddsbase = NULL;
3130         qboolean ddshasalpha = false;
3131         float ddsavgcolor[4];
3132         char basename[MAX_QPATH];
3133         int miplevel = R_PicmipForFlags(textureflags);
3134         int savemiplevel = miplevel;
3135         int mymiplevel;
3136
3137         if (cls.state == ca_dedicated)
3138                 return NULL;
3139
3140         // return an existing skinframe if already loaded
3141         // if loading of the first image fails, don't make a new skinframe as it
3142         // would cause all future lookups of this to be missing
3143         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3144         if (skinframe && skinframe->base)
3145                 return skinframe;
3146
3147         Image_StripImageExtension(name, basename, sizeof(basename));
3148
3149         // check for DDS texture file first
3150         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3151         {
3152                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3153                 if (basepixels == NULL)
3154                         return NULL;
3155         }
3156
3157         // FIXME handle miplevel
3158
3159         if (developer_loading.integer)
3160                 Con_Printf("loading skin \"%s\"\n", name);
3161
3162         // we've got some pixels to store, so really allocate this new texture now
3163         if (!skinframe)
3164                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3165         skinframe->stain = NULL;
3166         skinframe->merged = NULL;
3167         skinframe->base = NULL;
3168         skinframe->pants = NULL;
3169         skinframe->shirt = NULL;
3170         skinframe->nmap = NULL;
3171         skinframe->gloss = NULL;
3172         skinframe->glow = NULL;
3173         skinframe->fog = NULL;
3174         skinframe->reflect = NULL;
3175         skinframe->hasalpha = false;
3176
3177         if (ddsbase)
3178         {
3179                 skinframe->base = ddsbase;
3180                 skinframe->hasalpha = ddshasalpha;
3181                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3182                 if (r_loadfog && skinframe->hasalpha)
3183                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3184                 //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]);
3185         }
3186         else
3187         {
3188                 basepixels_width = image_width;
3189                 basepixels_height = image_height;
3190                 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);
3191                 if (textureflags & TEXF_ALPHA)
3192                 {
3193                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3194                         {
3195                                 if (basepixels[j] < 255)
3196                                 {
3197                                         skinframe->hasalpha = true;
3198                                         break;
3199                                 }
3200                         }
3201                         if (r_loadfog && skinframe->hasalpha)
3202                         {
3203                                 // has transparent pixels
3204                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3205                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3206                                 {
3207                                         pixels[j+0] = 255;
3208                                         pixels[j+1] = 255;
3209                                         pixels[j+2] = 255;
3210                                         pixels[j+3] = basepixels[j+3];
3211                                 }
3212                                 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);
3213                                 Mem_Free(pixels);
3214                         }
3215                 }
3216                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3217                 //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]);
3218                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3219                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3220                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3221                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3222         }
3223
3224         if (r_loaddds)
3225         {
3226                 mymiplevel = savemiplevel;
3227                 if (r_loadnormalmap)
3228                         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);
3229                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3230                 if (r_loadgloss)
3231                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3232                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3233                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3234                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3235         }
3236
3237         // _norm is the name used by tenebrae and has been adopted as standard
3238         if (r_loadnormalmap && skinframe->nmap == NULL)
3239         {
3240                 mymiplevel = savemiplevel;
3241                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3242                 {
3243                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3244                         Mem_Free(pixels);
3245                         pixels = NULL;
3246                 }
3247                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3248                 {
3249                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3250                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3251                         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);
3252                         Mem_Free(pixels);
3253                         Mem_Free(bumppixels);
3254                 }
3255                 else if (r_shadow_bumpscale_basetexture.value > 0)
3256                 {
3257                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3258                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3259                         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);
3260                         Mem_Free(pixels);
3261                 }
3262                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3263                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3264         }
3265
3266         // _luma is supported only for tenebrae compatibility
3267         // _glow is the preferred name
3268         mymiplevel = savemiplevel;
3269         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))))
3270         {
3271                 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);
3272                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3273                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3274                 Mem_Free(pixels);pixels = NULL;
3275         }
3276
3277         mymiplevel = savemiplevel;
3278         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3279         {
3280                 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);
3281                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3282                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3283                 Mem_Free(pixels);
3284                 pixels = NULL;
3285         }
3286
3287         mymiplevel = savemiplevel;
3288         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3289         {
3290                 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);
3291                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3292                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3293                 Mem_Free(pixels);
3294                 pixels = NULL;
3295         }
3296
3297         mymiplevel = savemiplevel;
3298         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3299         {
3300                 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);
3301                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3302                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3303                 Mem_Free(pixels);
3304                 pixels = NULL;
3305         }
3306
3307         mymiplevel = savemiplevel;
3308         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3309         {
3310                 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);
3311                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3312                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3313                 Mem_Free(pixels);
3314                 pixels = NULL;
3315         }
3316
3317         if (basepixels)
3318                 Mem_Free(basepixels);
3319
3320         return skinframe;
3321 }
3322
3323 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3324 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3325 {
3326         int i;
3327         unsigned char *temp1, *temp2;
3328         skinframe_t *skinframe;
3329
3330         if (cls.state == ca_dedicated)
3331                 return NULL;
3332
3333         // if already loaded just return it, otherwise make a new skinframe
3334         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3335         if (skinframe && skinframe->base)
3336                 return skinframe;
3337
3338         skinframe->stain = NULL;
3339         skinframe->merged = NULL;
3340         skinframe->base = NULL;
3341         skinframe->pants = NULL;
3342         skinframe->shirt = NULL;
3343         skinframe->nmap = NULL;
3344         skinframe->gloss = NULL;
3345         skinframe->glow = NULL;
3346         skinframe->fog = NULL;
3347         skinframe->reflect = NULL;
3348         skinframe->hasalpha = false;
3349
3350         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3351         if (!skindata)
3352                 return NULL;
3353
3354         if (developer_loading.integer)
3355                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3356
3357         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3358         {
3359                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3360                 temp2 = temp1 + width * height * 4;
3361                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3362                 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);
3363                 Mem_Free(temp1);
3364         }
3365         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3366         if (textureflags & TEXF_ALPHA)
3367         {
3368                 for (i = 3;i < width * height * 4;i += 4)
3369                 {
3370                         if (skindata[i] < 255)
3371                         {
3372                                 skinframe->hasalpha = true;
3373                                 break;
3374                         }
3375                 }
3376                 if (r_loadfog && skinframe->hasalpha)
3377                 {
3378                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3379                         memcpy(fogpixels, skindata, width * height * 4);
3380                         for (i = 0;i < width * height * 4;i += 4)
3381                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3382                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3383                         Mem_Free(fogpixels);
3384                 }
3385         }
3386
3387         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3388         //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]);
3389
3390         return skinframe;
3391 }
3392
3393 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3394 {
3395         int i;
3396         int featuresmask;
3397         skinframe_t *skinframe;
3398
3399         if (cls.state == ca_dedicated)
3400                 return NULL;
3401
3402         // if already loaded just return it, otherwise make a new skinframe
3403         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3404         if (skinframe && skinframe->base)
3405                 return skinframe;
3406
3407         skinframe->stain = NULL;
3408         skinframe->merged = NULL;
3409         skinframe->base = NULL;
3410         skinframe->pants = NULL;
3411         skinframe->shirt = NULL;
3412         skinframe->nmap = NULL;
3413         skinframe->gloss = NULL;
3414         skinframe->glow = NULL;
3415         skinframe->fog = NULL;
3416         skinframe->reflect = NULL;
3417         skinframe->hasalpha = false;
3418
3419         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3420         if (!skindata)
3421                 return NULL;
3422
3423         if (developer_loading.integer)
3424                 Con_Printf("loading quake skin \"%s\"\n", name);
3425
3426         // 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)
3427         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3428         memcpy(skinframe->qpixels, skindata, width*height);
3429         skinframe->qwidth = width;
3430         skinframe->qheight = height;
3431
3432         featuresmask = 0;
3433         for (i = 0;i < width * height;i++)
3434                 featuresmask |= palette_featureflags[skindata[i]];
3435
3436         skinframe->hasalpha = false;
3437         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3438         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3439         skinframe->qgeneratemerged = true;
3440         skinframe->qgeneratebase = skinframe->qhascolormapping;
3441         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3442
3443         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3444         //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]);
3445
3446         return skinframe;
3447 }
3448
3449 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3450 {
3451         int width;
3452         int height;
3453         unsigned char *skindata;
3454
3455         if (!skinframe->qpixels)
3456                 return;
3457
3458         if (!skinframe->qhascolormapping)
3459                 colormapped = false;
3460
3461         if (colormapped)
3462         {
3463                 if (!skinframe->qgeneratebase)
3464                         return;
3465         }
3466         else
3467         {
3468                 if (!skinframe->qgeneratemerged)
3469                         return;
3470         }
3471
3472         width = skinframe->qwidth;
3473         height = skinframe->qheight;
3474         skindata = skinframe->qpixels;
3475
3476         if (skinframe->qgeneratenmap)
3477         {
3478                 unsigned char *temp1, *temp2;
3479                 skinframe->qgeneratenmap = false;
3480                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3481                 temp2 = temp1 + width * height * 4;
3482                 // use either a custom palette or the quake palette
3483                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3484                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3485                 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);
3486                 Mem_Free(temp1);
3487         }
3488
3489         if (skinframe->qgenerateglow)
3490         {
3491                 skinframe->qgenerateglow = false;
3492                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3493         }
3494
3495         if (colormapped)
3496         {
3497                 skinframe->qgeneratebase = false;
3498                 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);
3499                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3500                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3501         }
3502         else
3503         {
3504                 skinframe->qgeneratemerged = false;
3505                 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);
3506         }
3507
3508         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3509         {
3510                 Mem_Free(skinframe->qpixels);
3511                 skinframe->qpixels = NULL;
3512         }
3513 }
3514
3515 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)
3516 {
3517         int i;
3518         skinframe_t *skinframe;
3519
3520         if (cls.state == ca_dedicated)
3521                 return NULL;
3522
3523         // if already loaded just return it, otherwise make a new skinframe
3524         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3525         if (skinframe && skinframe->base)
3526                 return skinframe;
3527
3528         skinframe->stain = NULL;
3529         skinframe->merged = NULL;
3530         skinframe->base = NULL;
3531         skinframe->pants = NULL;
3532         skinframe->shirt = NULL;
3533         skinframe->nmap = NULL;
3534         skinframe->gloss = NULL;
3535         skinframe->glow = NULL;
3536         skinframe->fog = NULL;
3537         skinframe->reflect = NULL;
3538         skinframe->hasalpha = false;
3539
3540         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3541         if (!skindata)
3542                 return NULL;
3543
3544         if (developer_loading.integer)
3545                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3546
3547         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3548         if (textureflags & TEXF_ALPHA)
3549         {
3550                 for (i = 0;i < width * height;i++)
3551                 {
3552                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3553                         {
3554                                 skinframe->hasalpha = true;
3555                                 break;
3556                         }
3557                 }
3558                 if (r_loadfog && skinframe->hasalpha)
3559                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3560         }
3561
3562         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3563         //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]);
3564
3565         return skinframe;
3566 }
3567
3568 skinframe_t *R_SkinFrame_LoadMissing(void)
3569 {
3570         skinframe_t *skinframe;
3571
3572         if (cls.state == ca_dedicated)
3573                 return NULL;
3574
3575         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3576         skinframe->stain = NULL;
3577         skinframe->merged = NULL;
3578         skinframe->base = NULL;
3579         skinframe->pants = NULL;
3580         skinframe->shirt = NULL;
3581         skinframe->nmap = NULL;
3582         skinframe->gloss = NULL;
3583         skinframe->glow = NULL;
3584         skinframe->fog = NULL;
3585         skinframe->reflect = NULL;
3586         skinframe->hasalpha = false;
3587
3588         skinframe->avgcolor[0] = rand() / RAND_MAX;
3589         skinframe->avgcolor[1] = rand() / RAND_MAX;
3590         skinframe->avgcolor[2] = rand() / RAND_MAX;
3591         skinframe->avgcolor[3] = 1;
3592
3593         return skinframe;
3594 }
3595
3596 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3597 typedef struct suffixinfo_s
3598 {
3599         const char *suffix;
3600         qboolean flipx, flipy, flipdiagonal;
3601 }
3602 suffixinfo_t;
3603 static suffixinfo_t suffix[3][6] =
3604 {
3605         {
3606                 {"px",   false, false, false},
3607                 {"nx",   false, false, false},
3608                 {"py",   false, false, false},
3609                 {"ny",   false, false, false},
3610                 {"pz",   false, false, false},
3611                 {"nz",   false, false, false}
3612         },
3613         {
3614                 {"posx", false, false, false},
3615                 {"negx", false, false, false},
3616                 {"posy", false, false, false},
3617                 {"negy", false, false, false},
3618                 {"posz", false, false, false},
3619                 {"negz", false, false, false}
3620         },
3621         {
3622                 {"rt",    true, false,  true},
3623                 {"lf",   false,  true,  true},
3624                 {"ft",    true,  true, false},
3625                 {"bk",   false, false, false},
3626                 {"up",    true, false,  true},
3627                 {"dn",    true, false,  true}
3628         }
3629 };
3630
3631 static int componentorder[4] = {0, 1, 2, 3};
3632
3633 rtexture_t *R_LoadCubemap(const char *basename)
3634 {
3635         int i, j, cubemapsize;
3636         unsigned char *cubemappixels, *image_buffer;
3637         rtexture_t *cubemaptexture;
3638         char name[256];
3639         // must start 0 so the first loadimagepixels has no requested width/height
3640         cubemapsize = 0;
3641         cubemappixels = NULL;
3642         cubemaptexture = NULL;
3643         // keep trying different suffix groups (posx, px, rt) until one loads
3644         for (j = 0;j < 3 && !cubemappixels;j++)
3645         {
3646                 // load the 6 images in the suffix group
3647                 for (i = 0;i < 6;i++)
3648                 {
3649                         // generate an image name based on the base and and suffix
3650                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3651                         // load it
3652                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3653                         {
3654                                 // an image loaded, make sure width and height are equal
3655                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3656                                 {
3657                                         // if this is the first image to load successfully, allocate the cubemap memory
3658                                         if (!cubemappixels && image_width >= 1)
3659                                         {
3660                                                 cubemapsize = image_width;
3661                                                 // note this clears to black, so unavailable sides are black
3662                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3663                                         }
3664                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3665                                         if (cubemappixels)
3666                                                 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);
3667                                 }
3668                                 else
3669                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3670                                 // free the image
3671                                 Mem_Free(image_buffer);
3672                         }
3673                 }
3674         }
3675         // if a cubemap loaded, upload it
3676         if (cubemappixels)
3677         {
3678                 if (developer_loading.integer)
3679                         Con_Printf("loading cubemap \"%s\"\n", basename);
3680
3681                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3682                 Mem_Free(cubemappixels);
3683         }
3684         else
3685         {
3686                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3687                 if (developer_loading.integer)
3688                 {
3689                         Con_Printf("(tried tried images ");
3690                         for (j = 0;j < 3;j++)
3691                                 for (i = 0;i < 6;i++)
3692                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3693                         Con_Print(" and was unable to find any of them).\n");
3694                 }
3695         }
3696         return cubemaptexture;
3697 }
3698
3699 rtexture_t *R_GetCubemap(const char *basename)
3700 {
3701         int i;
3702         for (i = 0;i < r_texture_numcubemaps;i++)
3703                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3704                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3705         if (i >= MAX_CUBEMAPS)
3706                 return r_texture_whitecube;
3707         r_texture_numcubemaps++;
3708         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3709         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3710         return r_texture_cubemaps[i].texture;
3711 }
3712
3713 void R_FreeCubemaps(void)
3714 {
3715         int i;
3716         for (i = 0;i < r_texture_numcubemaps;i++)
3717         {
3718                 if (developer_loading.integer)
3719                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3720                 if (r_texture_cubemaps[i].texture)
3721                         R_FreeTexture(r_texture_cubemaps[i].texture);
3722         }
3723         r_texture_numcubemaps = 0;
3724 }
3725
3726 void R_Main_FreeViewCache(void)
3727 {
3728         if (r_refdef.viewcache.entityvisible)
3729                 Mem_Free(r_refdef.viewcache.entityvisible);
3730         if (r_refdef.viewcache.world_pvsbits)
3731                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3732         if (r_refdef.viewcache.world_leafvisible)
3733                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3734         if (r_refdef.viewcache.world_surfacevisible)
3735                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3736         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3737 }
3738
3739 void R_Main_ResizeViewCache(void)
3740 {
3741         int numentities = r_refdef.scene.numentities;
3742         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3743         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3744         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3745         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3746         if (r_refdef.viewcache.maxentities < numentities)
3747         {
3748                 r_refdef.viewcache.maxentities = numentities;
3749                 if (r_refdef.viewcache.entityvisible)
3750                         Mem_Free(r_refdef.viewcache.entityvisible);
3751                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3752         }
3753         if (r_refdef.viewcache.world_numclusters != numclusters)
3754         {
3755                 r_refdef.viewcache.world_numclusters = numclusters;
3756                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3757                 if (r_refdef.viewcache.world_pvsbits)
3758                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3759                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3760         }
3761         if (r_refdef.viewcache.world_numleafs != numleafs)
3762         {
3763                 r_refdef.viewcache.world_numleafs = numleafs;
3764                 if (r_refdef.viewcache.world_leafvisible)
3765                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3766                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3767         }
3768         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3769         {
3770                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3771                 if (r_refdef.viewcache.world_surfacevisible)
3772                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3773                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3774         }
3775 }
3776
3777 extern rtexture_t *loadingscreentexture;
3778 void gl_main_start(void)
3779 {
3780         loadingscreentexture = NULL;
3781         r_texture_blanknormalmap = NULL;
3782         r_texture_white = NULL;
3783         r_texture_grey128 = NULL;
3784         r_texture_black = NULL;
3785         r_texture_whitecube = NULL;
3786         r_texture_normalizationcube = NULL;
3787         r_texture_fogattenuation = NULL;
3788         r_texture_fogheighttexture = NULL;
3789         r_texture_gammaramps = NULL;
3790         r_texture_numcubemaps = 0;
3791
3792         r_loaddds = r_texture_dds_load.integer != 0;
3793         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3794
3795         switch(vid.renderpath)
3796         {
3797         case RENDERPATH_GL20:
3798         case RENDERPATH_D3D9:
3799         case RENDERPATH_D3D10:
3800         case RENDERPATH_D3D11:
3801         case RENDERPATH_SOFT:
3802                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3803                 Cvar_SetValueQuick(&gl_combine, 1);
3804                 Cvar_SetValueQuick(&r_glsl, 1);
3805                 r_loadnormalmap = true;
3806                 r_loadgloss = true;
3807                 r_loadfog = false;
3808                 break;
3809         case RENDERPATH_GL13:
3810                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3811                 Cvar_SetValueQuick(&gl_combine, 1);
3812                 Cvar_SetValueQuick(&r_glsl, 0);
3813                 r_loadnormalmap = false;
3814                 r_loadgloss = false;
3815                 r_loadfog = true;
3816                 break;
3817         case RENDERPATH_GL11:
3818                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3819                 Cvar_SetValueQuick(&gl_combine, 0);
3820                 Cvar_SetValueQuick(&r_glsl, 0);
3821                 r_loadnormalmap = false;
3822                 r_loadgloss = false;
3823                 r_loadfog = true;
3824                 break;
3825         case RENDERPATH_GLES2:
3826                 Cvar_SetValueQuick(&r_textureunits, 1);
3827                 Cvar_SetValueQuick(&gl_combine, 1);
3828                 Cvar_SetValueQuick(&r_glsl, 1);
3829                 r_loadnormalmap = true;
3830                 r_loadgloss = false;
3831                 r_loadfog = false;
3832                 break;
3833         }
3834
3835         R_AnimCache_Free();
3836         R_FrameData_Reset();
3837
3838         r_numqueries = 0;
3839         r_maxqueries = 0;
3840         memset(r_queries, 0, sizeof(r_queries));
3841
3842         r_qwskincache = NULL;
3843         r_qwskincache_size = 0;
3844
3845         // set up r_skinframe loading system for textures
3846         memset(&r_skinframe, 0, sizeof(r_skinframe));
3847         r_skinframe.loadsequence = 1;
3848         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3849
3850         r_main_texturepool = R_AllocTexturePool();
3851         R_BuildBlankTextures();
3852         R_BuildNoTexture();
3853         if (vid.support.arb_texture_cube_map)
3854         {
3855                 R_BuildWhiteCube();
3856                 R_BuildNormalizationCube();
3857         }
3858         r_texture_fogattenuation = NULL;
3859         r_texture_fogheighttexture = NULL;
3860         r_texture_gammaramps = NULL;
3861         //r_texture_fogintensity = NULL;
3862         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3863         memset(&r_waterstate, 0, sizeof(r_waterstate));
3864         r_glsl_permutation = NULL;
3865         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3866         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3867         glslshaderstring = NULL;
3868 #ifdef SUPPORTD3D
3869         r_hlsl_permutation = NULL;
3870         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3871         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3872 #endif
3873         hlslshaderstring = NULL;
3874         memset(&r_svbsp, 0, sizeof (r_svbsp));
3875
3876         r_refdef.fogmasktable_density = 0;
3877 }
3878
3879 void gl_main_shutdown(void)
3880 {
3881         R_AnimCache_Free();
3882         R_FrameData_Reset();
3883
3884         R_Main_FreeViewCache();
3885
3886         switch(vid.renderpath)
3887         {
3888         case RENDERPATH_GL11:
3889         case RENDERPATH_GL13:
3890         case RENDERPATH_GL20:
3891         case RENDERPATH_GLES2:
3892                 if (r_maxqueries)
3893                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3894                 break;
3895         case RENDERPATH_D3D9:
3896                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3897                 break;
3898         case RENDERPATH_D3D10:
3899                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3900                 break;
3901         case RENDERPATH_D3D11:
3902                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3903                 break;
3904         case RENDERPATH_SOFT:
3905                 break;
3906         }
3907
3908         r_numqueries = 0;
3909         r_maxqueries = 0;
3910         memset(r_queries, 0, sizeof(r_queries));
3911
3912         r_qwskincache = NULL;
3913         r_qwskincache_size = 0;
3914
3915         // clear out the r_skinframe state
3916         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3917         memset(&r_skinframe, 0, sizeof(r_skinframe));
3918
3919         if (r_svbsp.nodes)
3920                 Mem_Free(r_svbsp.nodes);
3921         memset(&r_svbsp, 0, sizeof (r_svbsp));
3922         R_FreeTexturePool(&r_main_texturepool);
3923         loadingscreentexture = NULL;
3924         r_texture_blanknormalmap = NULL;
3925         r_texture_white = NULL;
3926         r_texture_grey128 = NULL;
3927         r_texture_black = NULL;
3928         r_texture_whitecube = NULL;
3929         r_texture_normalizationcube = NULL;
3930         r_texture_fogattenuation = NULL;
3931         r_texture_fogheighttexture = NULL;
3932         r_texture_gammaramps = NULL;
3933         r_texture_numcubemaps = 0;
3934         //r_texture_fogintensity = NULL;
3935         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3936         memset(&r_waterstate, 0, sizeof(r_waterstate));
3937         R_GLSL_Restart_f();
3938
3939         r_glsl_permutation = NULL;
3940         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3941         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3942         glslshaderstring = NULL;
3943 #ifdef SUPPORTD3D
3944         r_hlsl_permutation = NULL;
3945         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3946         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3947 #endif
3948         hlslshaderstring = NULL;
3949 }
3950
3951 extern void CL_ParseEntityLump(char *entitystring);
3952 void gl_main_newmap(void)
3953 {
3954         // FIXME: move this code to client
3955         char *entities, entname[MAX_QPATH];
3956         if (r_qwskincache)
3957                 Mem_Free(r_qwskincache);
3958         r_qwskincache = NULL;
3959         r_qwskincache_size = 0;
3960         if (cl.worldmodel)
3961         {
3962                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3963                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3964                 {
3965                         CL_ParseEntityLump(entities);
3966                         Mem_Free(entities);
3967                         return;
3968                 }
3969                 if (cl.worldmodel->brush.entities)
3970                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3971         }
3972         R_Main_FreeViewCache();
3973
3974         R_FrameData_Reset();
3975 }
3976
3977 void GL_Main_Init(void)
3978 {
3979         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3980
3981         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3982         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3983         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3984         if (gamemode == GAME_NEHAHRA)
3985         {
3986                 Cvar_RegisterVariable (&gl_fogenable);
3987                 Cvar_RegisterVariable (&gl_fogdensity);
3988                 Cvar_RegisterVariable (&gl_fogred);
3989                 Cvar_RegisterVariable (&gl_foggreen);
3990                 Cvar_RegisterVariable (&gl_fogblue);
3991                 Cvar_RegisterVariable (&gl_fogstart);
3992                 Cvar_RegisterVariable (&gl_fogend);
3993                 Cvar_RegisterVariable (&gl_skyclip);
3994         }
3995         Cvar_RegisterVariable(&r_motionblur);
3996         Cvar_RegisterVariable(&r_motionblur_maxblur);
3997         Cvar_RegisterVariable(&r_motionblur_bmin);
3998         Cvar_RegisterVariable(&r_motionblur_vmin);
3999         Cvar_RegisterVariable(&r_motionblur_vmax);
4000         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4001         Cvar_RegisterVariable(&r_motionblur_randomize);
4002         Cvar_RegisterVariable(&r_damageblur);
4003         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4004         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4005         Cvar_RegisterVariable(&r_equalize_entities_by);
4006         Cvar_RegisterVariable(&r_equalize_entities_to);
4007         Cvar_RegisterVariable(&r_depthfirst);
4008         Cvar_RegisterVariable(&r_useinfinitefarclip);
4009         Cvar_RegisterVariable(&r_farclip_base);
4010         Cvar_RegisterVariable(&r_farclip_world);
4011         Cvar_RegisterVariable(&r_nearclip);
4012         Cvar_RegisterVariable(&r_showbboxes);
4013         Cvar_RegisterVariable(&r_showsurfaces);
4014         Cvar_RegisterVariable(&r_showtris);
4015         Cvar_RegisterVariable(&r_shownormals);
4016         Cvar_RegisterVariable(&r_showlighting);
4017         Cvar_RegisterVariable(&r_showshadowvolumes);
4018         Cvar_RegisterVariable(&r_showcollisionbrushes);
4019         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4020         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4021         Cvar_RegisterVariable(&r_showdisabledepthtest);
4022         Cvar_RegisterVariable(&r_drawportals);
4023         Cvar_RegisterVariable(&r_drawentities);
4024         Cvar_RegisterVariable(&r_draw2d);
4025         Cvar_RegisterVariable(&r_drawworld);
4026         Cvar_RegisterVariable(&r_cullentities_trace);
4027         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4028         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4029         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4030         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4031         Cvar_RegisterVariable(&r_drawviewmodel);
4032         Cvar_RegisterVariable(&r_drawexteriormodel);
4033         Cvar_RegisterVariable(&r_speeds);
4034         Cvar_RegisterVariable(&r_fullbrights);
4035         Cvar_RegisterVariable(&r_wateralpha);
4036         Cvar_RegisterVariable(&r_dynamic);
4037         Cvar_RegisterVariable(&r_fakelight);
4038         Cvar_RegisterVariable(&r_fakelight_intensity);
4039         Cvar_RegisterVariable(&r_fullbright);
4040         Cvar_RegisterVariable(&r_shadows);
4041         Cvar_RegisterVariable(&r_shadows_darken);
4042         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4043         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4044         Cvar_RegisterVariable(&r_shadows_throwdistance);
4045         Cvar_RegisterVariable(&r_shadows_throwdirection);
4046         Cvar_RegisterVariable(&r_shadows_focus);
4047         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4048         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4049         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4050         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4051         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4052         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4053         Cvar_RegisterVariable(&r_fog_exp2);
4054         Cvar_RegisterVariable(&r_drawfog);
4055         Cvar_RegisterVariable(&r_transparentdepthmasking);
4056         Cvar_RegisterVariable(&r_texture_dds_load);
4057         Cvar_RegisterVariable(&r_texture_dds_save);
4058         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4059         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4060         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4061         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4062         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4063         Cvar_RegisterVariable(&r_textureunits);
4064         Cvar_RegisterVariable(&gl_combine);
4065         Cvar_RegisterVariable(&r_glsl);
4066         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4067         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4068         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4069         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4070         Cvar_RegisterVariable(&r_glsl_postprocess);
4071         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4072         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4073         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4074         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4075         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4076         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4077         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4078         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4079
4080         Cvar_RegisterVariable(&r_water);
4081         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4082         Cvar_RegisterVariable(&r_water_clippingplanebias);
4083         Cvar_RegisterVariable(&r_water_refractdistort);
4084         Cvar_RegisterVariable(&r_water_reflectdistort);
4085         Cvar_RegisterVariable(&r_water_scissormode);
4086         Cvar_RegisterVariable(&r_lerpsprites);
4087         Cvar_RegisterVariable(&r_lerpmodels);
4088         Cvar_RegisterVariable(&r_lerplightstyles);
4089         Cvar_RegisterVariable(&r_waterscroll);
4090         Cvar_RegisterVariable(&r_bloom);
4091         Cvar_RegisterVariable(&r_bloom_colorscale);
4092         Cvar_RegisterVariable(&r_bloom_brighten);
4093         Cvar_RegisterVariable(&r_bloom_blur);
4094         Cvar_RegisterVariable(&r_bloom_resolution);
4095         Cvar_RegisterVariable(&r_bloom_colorexponent);
4096         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4097         Cvar_RegisterVariable(&r_hdr);
4098         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4099         Cvar_RegisterVariable(&r_hdr_glowintensity);
4100         Cvar_RegisterVariable(&r_hdr_range);
4101         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4102         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4103         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4104         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4105         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4106         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4107         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4108         Cvar_RegisterVariable(&developer_texturelogging);
4109         Cvar_RegisterVariable(&gl_lightmaps);
4110         Cvar_RegisterVariable(&r_test);
4111         Cvar_RegisterVariable(&r_glsl_saturation);
4112         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4113         Cvar_RegisterVariable(&r_framedatasize);
4114         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4115                 Cvar_SetValue("r_fullbrights", 0);
4116         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4117
4118         Cvar_RegisterVariable(&r_track_sprites);
4119         Cvar_RegisterVariable(&r_track_sprites_flags);
4120         Cvar_RegisterVariable(&r_track_sprites_scalew);
4121         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4122         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4123         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4124         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4125         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4126 }
4127
4128 extern void R_Textures_Init(void);
4129 extern void GL_Draw_Init(void);
4130 extern void GL_Main_Init(void);
4131 extern void R_Shadow_Init(void);
4132 extern void R_Sky_Init(void);
4133 extern void GL_Surf_Init(void);
4134 extern void R_Particles_Init(void);
4135 extern void R_Explosion_Init(void);
4136 extern void gl_backend_init(void);
4137 extern void Sbar_Init(void);
4138 extern void R_LightningBeams_Init(void);
4139 extern void Mod_RenderInit(void);
4140 extern void Font_Init(void);
4141
4142 void Render_Init(void)
4143 {
4144         gl_backend_init();
4145         R_Textures_Init();
4146         GL_Main_Init();
4147         Font_Init();
4148         GL_Draw_Init();
4149         R_Shadow_Init();
4150         R_Sky_Init();
4151         GL_Surf_Init();
4152         Sbar_Init();
4153         R_Particles_Init();
4154         R_Explosion_Init();
4155         R_LightningBeams_Init();
4156         Mod_RenderInit();
4157 }
4158
4159 /*
4160 ===============
4161 GL_Init
4162 ===============
4163 */
4164 extern char *ENGINE_EXTENSIONS;
4165 void GL_Init (void)
4166 {
4167         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4168         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4169         gl_version = (const char *)qglGetString(GL_VERSION);
4170         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4171
4172         if (!gl_extensions)
4173                 gl_extensions = "";
4174         if (!gl_platformextensions)
4175                 gl_platformextensions = "";
4176
4177         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4178         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4179         Con_Printf("GL_VERSION: %s\n", gl_version);
4180         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4181         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4182
4183         VID_CheckExtensions();
4184
4185         // LordHavoc: report supported extensions
4186         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4187
4188         // clear to black (loading plaque will be seen over this)
4189         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4190 }
4191
4192 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4193 {
4194         int i;
4195         mplane_t *p;
4196         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4197         {
4198                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4199                 if (i == 4)
4200                         continue;
4201                 p = r_refdef.view.frustum + i;
4202                 switch(p->signbits)
4203                 {
4204                 default:
4205                 case 0:
4206                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4207                                 return true;
4208                         break;
4209                 case 1:
4210                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4211                                 return true;
4212                         break;
4213                 case 2:
4214                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4215                                 return true;
4216                         break;
4217                 case 3:
4218                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4219                                 return true;
4220                         break;
4221                 case 4:
4222                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4223                                 return true;
4224                         break;
4225                 case 5:
4226                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4227                                 return true;
4228                         break;
4229                 case 6:
4230                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4231                                 return true;
4232                         break;
4233                 case 7:
4234                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4235                                 return true;
4236                         break;
4237                 }
4238         }
4239         return false;
4240 }
4241
4242 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4243 {
4244         int i;
4245         const mplane_t *p;
4246         for (i = 0;i < numplanes;i++)
4247         {
4248                 p = planes + i;
4249                 switch(p->signbits)
4250                 {
4251                 default:
4252                 case 0:
4253                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4254                                 return true;
4255                         break;
4256                 case 1:
4257                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 2:
4261                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 3:
4265                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 case 4:
4269                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4270                                 return true;
4271                         break;
4272                 case 5:
4273                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274                                 return true;
4275                         break;
4276                 case 6:
4277                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4278                                 return true;
4279                         break;
4280                 case 7:
4281                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4282                                 return true;
4283                         break;
4284                 }
4285         }
4286         return false;
4287 }
4288
4289 //==================================================================================
4290
4291 // LordHavoc: this stores temporary data used within the same frame
4292
4293 typedef struct r_framedata_mem_s
4294 {
4295         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4296         size_t size; // how much usable space
4297         size_t current; // how much space in use
4298         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4299         size_t wantedsize; // how much space was allocated
4300         unsigned char *data; // start of real data (16byte aligned)
4301 }
4302 r_framedata_mem_t;
4303
4304 static r_framedata_mem_t *r_framedata_mem;
4305
4306 void R_FrameData_Reset(void)
4307 {
4308         while (r_framedata_mem)
4309         {
4310                 r_framedata_mem_t *next = r_framedata_mem->purge;
4311                 Mem_Free(r_framedata_mem);
4312                 r_framedata_mem = next;
4313         }
4314 }
4315
4316 void R_FrameData_Resize(void)
4317 {
4318         size_t wantedsize;
4319         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4320         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4321         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4322         {
4323                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4324                 newmem->wantedsize = wantedsize;
4325                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4326                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4327                 newmem->current = 0;
4328                 newmem->mark = 0;
4329                 newmem->purge = r_framedata_mem;
4330                 r_framedata_mem = newmem;
4331         }
4332 }
4333
4334 void R_FrameData_NewFrame(void)
4335 {
4336         R_FrameData_Resize();
4337         if (!r_framedata_mem)
4338                 return;
4339         // if we ran out of space on the last frame, free the old memory now
4340         while (r_framedata_mem->purge)
4341         {
4342                 // repeatedly remove the second item in the list, leaving only head
4343                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4344                 Mem_Free(r_framedata_mem->purge);
4345                 r_framedata_mem->purge = next;
4346         }
4347         // reset the current mem pointer
4348         r_framedata_mem->current = 0;
4349         r_framedata_mem->mark = 0;
4350 }
4351
4352 void *R_FrameData_Alloc(size_t size)
4353 {
4354         void *data;
4355
4356         // align to 16 byte boundary - the data pointer is already aligned, so we
4357         // only need to ensure the size of every allocation is also aligned
4358         size = (size + 15) & ~15;
4359
4360         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4361         {
4362                 // emergency - we ran out of space, allocate more memory
4363                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4364                 R_FrameData_Resize();
4365         }
4366
4367         data = r_framedata_mem->data + r_framedata_mem->current;
4368         r_framedata_mem->current += size;
4369
4370         // count the usage for stats
4371         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4372         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4373
4374         return (void *)data;
4375 }
4376
4377 void *R_FrameData_Store(size_t size, void *data)
4378 {
4379         void *d = R_FrameData_Alloc(size);
4380         if (d && data)
4381                 memcpy(d, data, size);
4382         return d;
4383 }
4384
4385 void R_FrameData_SetMark(void)
4386 {
4387         if (!r_framedata_mem)
4388                 return;
4389         r_framedata_mem->mark = r_framedata_mem->current;
4390 }
4391
4392 void R_FrameData_ReturnToMark(void)
4393 {
4394         if (!r_framedata_mem)
4395                 return;
4396         r_framedata_mem->current = r_framedata_mem->mark;
4397 }
4398
4399 //==================================================================================
4400
4401 // LordHavoc: animcache originally written by Echon, rewritten since then
4402
4403 /**
4404  * Animation cache prevents re-generating mesh data for an animated model
4405  * multiple times in one frame for lighting, shadowing, reflections, etc.
4406  */
4407
4408 void R_AnimCache_Free(void)
4409 {
4410 }
4411
4412 void R_AnimCache_ClearCache(void)
4413 {
4414         int i;
4415         entity_render_t *ent;
4416
4417         for (i = 0;i < r_refdef.scene.numentities;i++)
4418         {
4419                 ent = r_refdef.scene.entities[i];
4420                 ent->animcache_vertex3f = NULL;
4421                 ent->animcache_normal3f = NULL;
4422                 ent->animcache_svector3f = NULL;
4423                 ent->animcache_tvector3f = NULL;
4424                 ent->animcache_vertexmesh = NULL;
4425                 ent->animcache_vertex3fbuffer = NULL;
4426                 ent->animcache_vertexmeshbuffer = NULL;
4427         }
4428 }
4429
4430 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4431 {
4432         int i;
4433
4434         // check if we need the meshbuffers
4435         if (!vid.useinterleavedarrays)
4436                 return;
4437
4438         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4439                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4440         // TODO: upload vertex3f buffer?
4441         if (ent->animcache_vertexmesh)
4442         {
4443                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4444                 for (i = 0;i < numvertices;i++)
4445                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4446                 if (ent->animcache_svector3f)
4447                         for (i = 0;i < numvertices;i++)
4448                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4449                 if (ent->animcache_tvector3f)
4450                         for (i = 0;i < numvertices;i++)
4451                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4452                 if (ent->animcache_normal3f)
4453                         for (i = 0;i < numvertices;i++)
4454                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4455                 // TODO: upload vertexmeshbuffer?
4456         }
4457 }
4458
4459 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4460 {
4461         dp_model_t *model = ent->model;
4462         int numvertices;
4463         // see if it's already cached this frame
4464         if (ent->animcache_vertex3f)
4465         {
4466                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4467                 if (wantnormals || wanttangents)
4468                 {
4469                         if (ent->animcache_normal3f)
4470                                 wantnormals = false;
4471                         if (ent->animcache_svector3f)
4472                                 wanttangents = false;
4473                         if (wantnormals || wanttangents)
4474                         {
4475                                 numvertices = model->surfmesh.num_vertices;
4476                                 if (wantnormals)
4477                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4478                                 if (wanttangents)
4479                                 {
4480                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4481                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4482                                 }
4483                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4484                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4485                         }
4486                 }
4487         }
4488         else
4489         {
4490                 // see if this ent is worth caching
4491                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4492                         return false;
4493                 // get some memory for this entity and generate mesh data
4494                 numvertices = model->surfmesh.num_vertices;
4495                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4496                 if (wantnormals)
4497                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4498                 if (wanttangents)
4499                 {
4500                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4502                 }
4503                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4504                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4505         }
4506         return true;
4507 }
4508
4509 void R_AnimCache_CacheVisibleEntities(void)
4510 {
4511         int i;
4512         qboolean wantnormals = true;
4513         qboolean wanttangents = !r_showsurfaces.integer;
4514
4515         switch(vid.renderpath)
4516         {
4517         case RENDERPATH_GL20:
4518         case RENDERPATH_D3D9:
4519         case RENDERPATH_D3D10:
4520         case RENDERPATH_D3D11:
4521         case RENDERPATH_GLES2:
4522                 break;
4523         case RENDERPATH_GL13:
4524         case RENDERPATH_GL11:
4525                 wanttangents = false;
4526                 break;
4527         case RENDERPATH_SOFT:
4528                 break;
4529         }
4530
4531         if (r_shownormals.integer)
4532                 wanttangents = wantnormals = true;
4533
4534         // TODO: thread this
4535         // NOTE: R_PrepareRTLights() also caches entities
4536
4537         for (i = 0;i < r_refdef.scene.numentities;i++)
4538                 if (r_refdef.viewcache.entityvisible[i])
4539                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4540 }
4541
4542 //==================================================================================
4543
4544 static void R_View_UpdateEntityLighting (void)
4545 {
4546         int i;
4547         entity_render_t *ent;
4548         vec3_t tempdiffusenormal, avg;
4549         vec_t f, fa, fd, fdd;
4550         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4551
4552         for (i = 0;i < r_refdef.scene.numentities;i++)
4553         {
4554                 ent = r_refdef.scene.entities[i];
4555
4556                 // skip unseen models
4557                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4558                         continue;
4559
4560                 // skip bsp models
4561                 if (ent->model && ent->model->brush.num_leafs)
4562                 {
4563                         // TODO: use modellight for r_ambient settings on world?
4564                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4565                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4566                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4567                         continue;
4568                 }
4569
4570                 // fetch the lighting from the worldmodel data
4571                 VectorClear(ent->modellight_ambient);
4572                 VectorClear(ent->modellight_diffuse);
4573                 VectorClear(tempdiffusenormal);
4574                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4575                 {
4576                         vec3_t org;
4577                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4578
4579                         // complete lightning for lit sprites
4580                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4581                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4582                         {
4583                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4584                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4585                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4586                         }
4587                         else
4588                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4589
4590                         if(ent->flags & RENDER_EQUALIZE)
4591                         {
4592                                 // first fix up ambient lighting...
4593                                 if(r_equalize_entities_minambient.value > 0)
4594                                 {
4595                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4596                                         if(fd > 0)
4597                                         {
4598                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4599                                                 if(fa < r_equalize_entities_minambient.value * fd)
4600                                                 {
4601                                                         // solve:
4602                                                         //   fa'/fd' = minambient
4603                                                         //   fa'+0.25*fd' = fa+0.25*fd
4604                                                         //   ...
4605                                                         //   fa' = fd' * minambient
4606                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4607                                                         //   ...
4608                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4609                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4610                                                         //   ...
4611                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4612                                                         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
4613                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4614                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4615                                                 }
4616                                         }
4617                                 }
4618
4619                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4620                                 {
4621                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4622                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4623                                         f = fa + 0.25 * fd;
4624                                         if(f > 0)
4625                                         {
4626                                                 // adjust brightness and saturation to target
4627                                                 avg[0] = avg[1] = avg[2] = fa / f;
4628                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4629                                                 avg[0] = avg[1] = avg[2] = fd / f;
4630                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4631                                         }
4632                                 }
4633                         }
4634                 }
4635                 else // highly rare
4636                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4637
4638                 // move the light direction into modelspace coordinates for lighting code
4639                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4640                 if(VectorLength2(ent->modellight_lightdir) == 0)
4641                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4642                 VectorNormalize(ent->modellight_lightdir);
4643         }
4644 }
4645
4646 #define MAX_LINEOFSIGHTTRACES 64
4647
4648 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4649 {
4650         int i;
4651         vec3_t boxmins, boxmaxs;
4652         vec3_t start;
4653         vec3_t end;
4654         dp_model_t *model = r_refdef.scene.worldmodel;
4655
4656         if (!model || !model->brush.TraceLineOfSight)
4657                 return true;
4658
4659         // expand the box a little
4660         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4661         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4662         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4663         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4664         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4665         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4666
4667         // return true if eye is inside enlarged box
4668         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4669                 return true;
4670
4671         // try center
4672         VectorCopy(eye, start);
4673         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4674         if (model->brush.TraceLineOfSight(model, start, end))
4675                 return true;
4676
4677         // try various random positions
4678         for (i = 0;i < numsamples;i++)
4679         {
4680                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4681                 if (model->brush.TraceLineOfSight(model, start, end))
4682                         return true;
4683         }
4684
4685         return false;
4686 }
4687
4688
4689 static void R_View_UpdateEntityVisible (void)
4690 {
4691         int i;
4692         int renderimask;
4693         int samples;
4694         entity_render_t *ent;
4695
4696         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4697                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4698                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4699                 :                                                          RENDER_EXTERIORMODEL;
4700         if (!r_drawviewmodel.integer)
4701                 renderimask |= RENDER_VIEWMODEL;
4702         if (!r_drawexteriormodel.integer)
4703                 renderimask |= RENDER_EXTERIORMODEL;
4704         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4705         {
4706                 // worldmodel can check visibility
4707                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4708                 for (i = 0;i < r_refdef.scene.numentities;i++)
4709                 {
4710                         ent = r_refdef.scene.entities[i];
4711                         if (!(ent->flags & renderimask))
4712                         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)))
4713                         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))
4714                                 r_refdef.viewcache.entityvisible[i] = true;
4715                 }
4716                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4717                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4718                 {
4719                         for (i = 0;i < r_refdef.scene.numentities;i++)
4720                         {
4721                                 ent = r_refdef.scene.entities[i];
4722                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4723                                 {
4724                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4725                                         if (samples < 0)
4726                                                 continue; // temp entities do pvs only
4727                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4728                                                 ent->last_trace_visibility = realtime;
4729                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4730                                                 r_refdef.viewcache.entityvisible[i] = 0;
4731                                 }
4732                         }
4733                 }
4734         }
4735         else
4736         {
4737                 // no worldmodel or it can't check visibility
4738                 for (i = 0;i < r_refdef.scene.numentities;i++)
4739                 {
4740                         ent = r_refdef.scene.entities[i];
4741                         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));
4742                 }
4743         }
4744 }
4745
4746 /// only used if skyrendermasked, and normally returns false
4747 int R_DrawBrushModelsSky (void)
4748 {
4749         int i, sky;
4750         entity_render_t *ent;
4751
4752         sky = false;
4753         for (i = 0;i < r_refdef.scene.numentities;i++)
4754         {
4755                 if (!r_refdef.viewcache.entityvisible[i])
4756                         continue;
4757                 ent = r_refdef.scene.entities[i];
4758                 if (!ent->model || !ent->model->DrawSky)
4759                         continue;
4760                 ent->model->DrawSky(ent);
4761                 sky = true;
4762         }
4763         return sky;
4764 }
4765
4766 static void R_DrawNoModel(entity_render_t *ent);
4767 static void R_DrawModels(void)
4768 {
4769         int i;
4770         entity_render_t *ent;
4771
4772         for (i = 0;i < r_refdef.scene.numentities;i++)
4773         {
4774                 if (!r_refdef.viewcache.entityvisible[i])
4775                         continue;
4776                 ent = r_refdef.scene.entities[i];
4777                 r_refdef.stats.entities++;
4778                 if (ent->model && ent->model->Draw != NULL)
4779                         ent->model->Draw(ent);
4780                 else
4781                         R_DrawNoModel(ent);
4782         }
4783 }
4784
4785 static void R_DrawModelsDepth(void)
4786 {
4787         int i;
4788         entity_render_t *ent;
4789
4790         for (i = 0;i < r_refdef.scene.numentities;i++)
4791         {
4792                 if (!r_refdef.viewcache.entityvisible[i])
4793                         continue;
4794                 ent = r_refdef.scene.entities[i];
4795                 if (ent->model && ent->model->DrawDepth != NULL)
4796                         ent->model->DrawDepth(ent);
4797         }
4798 }
4799
4800 static void R_DrawModelsDebug(void)
4801 {
4802         int i;
4803         entity_render_t *ent;
4804
4805         for (i = 0;i < r_refdef.scene.numentities;i++)
4806         {
4807                 if (!r_refdef.viewcache.entityvisible[i])
4808                         continue;
4809                 ent = r_refdef.scene.entities[i];
4810                 if (ent->model && ent->model->DrawDebug != NULL)
4811                         ent->model->DrawDebug(ent);
4812         }
4813 }
4814
4815 static void R_DrawModelsAddWaterPlanes(void)
4816 {
4817         int i;
4818         entity_render_t *ent;
4819
4820         for (i = 0;i < r_refdef.scene.numentities;i++)
4821         {
4822                 if (!r_refdef.viewcache.entityvisible[i])
4823                         continue;
4824                 ent = r_refdef.scene.entities[i];
4825                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4826                         ent->model->DrawAddWaterPlanes(ent);
4827         }
4828 }
4829
4830 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4831 {
4832         if (r_hdr_irisadaptation.integer)
4833         {
4834                 vec3_t ambient;
4835                 vec3_t diffuse;
4836                 vec3_t diffusenormal;
4837                 vec_t brightness;
4838                 vec_t goal;
4839                 vec_t adjust;
4840                 vec_t current;
4841                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4842                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4843                 brightness = max(0.0000001f, brightness);
4844                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4845                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4846                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4847                 current = r_hdr_irisadaptation_value.value;
4848                 if (current < goal)
4849                         current = min(current + adjust, goal);
4850                 else if (current > goal)
4851                         current = max(current - adjust, goal);
4852                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4853                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4854         }
4855         else if (r_hdr_irisadaptation_value.value != 1.0f)
4856                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4857 }
4858
4859 static void R_View_SetFrustum(const int *scissor)
4860 {
4861         int i;
4862         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4863         vec3_t forward, left, up, origin, v;
4864
4865         if(scissor)
4866         {
4867                 // flipped x coordinates (because x points left here)
4868                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4869                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4870
4871                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4872                 switch(vid.renderpath)
4873                 {
4874                         case RENDERPATH_D3D9:
4875                         case RENDERPATH_D3D10:
4876                         case RENDERPATH_D3D11:
4877                         case RENDERPATH_SOFT:
4878                                 // non-flipped y coordinates
4879                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4880                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4881                                 break;
4882                         case RENDERPATH_GL11:
4883                         case RENDERPATH_GL13:
4884                         case RENDERPATH_GL20:
4885                         case RENDERPATH_GLES2:
4886                                 // non-flipped y coordinates
4887                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4888                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4889                                 break;
4890                 }
4891         }
4892
4893         // we can't trust r_refdef.view.forward and friends in reflected scenes
4894         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4895
4896 #if 0
4897         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4898         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4899         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4900         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4901         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4902         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4903         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4904         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4905         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4906         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4907         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4908         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4909 #endif
4910
4911 #if 0
4912         zNear = r_refdef.nearclip;
4913         nudge = 1.0 - 1.0 / (1<<23);
4914         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4915         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4916         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4917         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4918         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4919         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4920         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4921         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4922 #endif
4923
4924
4925
4926 #if 0
4927         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4928         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4929         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4930         r_refdef.view.frustum[0].dist = m[15] - m[12];
4931
4932         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4933         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4934         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4935         r_refdef.view.frustum[1].dist = m[15] + m[12];
4936
4937         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4938         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4939         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4940         r_refdef.view.frustum[2].dist = m[15] - m[13];
4941
4942         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4943         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4944         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4945         r_refdef.view.frustum[3].dist = m[15] + m[13];
4946
4947         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4948         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4949         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4950         r_refdef.view.frustum[4].dist = m[15] - m[14];
4951
4952         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4953         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4954         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4955         r_refdef.view.frustum[5].dist = m[15] + m[14];
4956 #endif
4957
4958         if (r_refdef.view.useperspective)
4959         {
4960                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4961                 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]);
4962                 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]);
4963                 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]);
4964                 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]);
4965
4966                 // then the normals from the corners relative to origin
4967                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4968                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4969                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4970                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4971
4972                 // in a NORMAL view, forward cross left == up
4973                 // in a REFLECTED view, forward cross left == down
4974                 // so our cross products above need to be adjusted for a left handed coordinate system
4975                 CrossProduct(forward, left, v);
4976                 if(DotProduct(v, up) < 0)
4977                 {
4978                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4979                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
4980                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
4981                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
4982                 }
4983
4984                 // Leaving those out was a mistake, those were in the old code, and they
4985                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
4986                 // I couldn't reproduce it after adding those normalizations. --blub
4987                 VectorNormalize(r_refdef.view.frustum[0].normal);
4988                 VectorNormalize(r_refdef.view.frustum[1].normal);
4989                 VectorNormalize(r_refdef.view.frustum[2].normal);
4990                 VectorNormalize(r_refdef.view.frustum[3].normal);
4991
4992                 // make the corners absolute
4993                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
4994                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
4995                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
4996                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
4997
4998                 // one more normal
4999                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5000
5001                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5002                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5003                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5004                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5005                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5006         }
5007         else
5008         {
5009                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5010                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5011                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5012                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5013                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5014                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5015                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5016                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5017                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5018                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5019         }
5020         r_refdef.view.numfrustumplanes = 5;
5021
5022         if (r_refdef.view.useclipplane)
5023         {
5024                 r_refdef.view.numfrustumplanes = 6;
5025                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5026         }
5027
5028         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5029                 PlaneClassify(r_refdef.view.frustum + i);
5030
5031         // LordHavoc: note to all quake engine coders, Quake had a special case
5032         // for 90 degrees which assumed a square view (wrong), so I removed it,
5033         // Quake2 has it disabled as well.
5034
5035         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5036         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5037         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5038         //PlaneClassify(&frustum[0]);
5039
5040         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5041         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5042         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5043         //PlaneClassify(&frustum[1]);
5044
5045         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5046         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5047         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5048         //PlaneClassify(&frustum[2]);
5049
5050         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5051         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5052         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5053         //PlaneClassify(&frustum[3]);
5054
5055         // nearclip plane
5056         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5057         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5058         //PlaneClassify(&frustum[4]);
5059 }
5060
5061 void R_View_UpdateWithScissor(const int *myscissor)
5062 {
5063         R_Main_ResizeViewCache();
5064         R_View_SetFrustum(myscissor);
5065         R_View_WorldVisibility(r_refdef.view.useclipplane);
5066         R_View_UpdateEntityVisible();
5067         R_View_UpdateEntityLighting();
5068 }
5069
5070 void R_View_Update(void)
5071 {
5072         R_Main_ResizeViewCache();
5073         R_View_SetFrustum(NULL);
5074         R_View_WorldVisibility(r_refdef.view.useclipplane);
5075         R_View_UpdateEntityVisible();
5076         R_View_UpdateEntityLighting();
5077 }
5078
5079 void R_SetupView(qboolean allowwaterclippingplane)
5080 {
5081         const float *customclipplane = NULL;
5082         float plane[4];
5083         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5084         {
5085                 // LordHavoc: couldn't figure out how to make this approach the
5086                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5087                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5088                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5089                         dist = r_refdef.view.clipplane.dist;
5090                 plane[0] = r_refdef.view.clipplane.normal[0];
5091                 plane[1] = r_refdef.view.clipplane.normal[1];
5092                 plane[2] = r_refdef.view.clipplane.normal[2];
5093                 plane[3] = dist;
5094                 customclipplane = plane;
5095         }
5096
5097         if (!r_refdef.view.useperspective)
5098                 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);
5099         else if (vid.stencil && r_useinfinitefarclip.integer)
5100                 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);
5101         else
5102                 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);
5103         R_SetViewport(&r_refdef.view.viewport);
5104 }
5105
5106 void R_EntityMatrix(const matrix4x4_t *matrix)
5107 {
5108         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5109         {
5110                 gl_modelmatrixchanged = false;
5111                 gl_modelmatrix = *matrix;
5112                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5113                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5114                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5115                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5116                 CHECKGLERROR
5117                 switch(vid.renderpath)
5118                 {
5119                 case RENDERPATH_D3D9:
5120 #ifdef SUPPORTD3D
5121                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5122                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5123 #endif
5124                         break;
5125                 case RENDERPATH_D3D10:
5126                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5127                         break;
5128                 case RENDERPATH_D3D11:
5129                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5130                         break;
5131                 case RENDERPATH_GL13:
5132                 case RENDERPATH_GL11:
5133                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5134                         break;
5135                 case RENDERPATH_SOFT:
5136                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5137                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5138                         break;
5139                 case RENDERPATH_GL20:
5140                 case RENDERPATH_GLES2:
5141                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5142                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5143                         break;
5144                 }
5145         }
5146 }
5147
5148 void R_ResetViewRendering2D(void)
5149 {
5150         r_viewport_t viewport;
5151         DrawQ_Finish();
5152
5153         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5154         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);
5155         R_SetViewport(&viewport);
5156         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5157         GL_Color(1, 1, 1, 1);
5158         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5159         GL_BlendFunc(GL_ONE, GL_ZERO);
5160         GL_ScissorTest(false);
5161         GL_DepthMask(false);
5162         GL_DepthRange(0, 1);
5163         GL_DepthTest(false);
5164         GL_DepthFunc(GL_LEQUAL);
5165         R_EntityMatrix(&identitymatrix);
5166         R_Mesh_ResetTextureState();
5167         GL_PolygonOffset(0, 0);
5168         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5169         switch(vid.renderpath)
5170         {
5171         case RENDERPATH_GL11:
5172         case RENDERPATH_GL13:
5173         case RENDERPATH_GL20:
5174         case RENDERPATH_GLES2:
5175                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5176                 break;
5177         case RENDERPATH_D3D9:
5178         case RENDERPATH_D3D10:
5179         case RENDERPATH_D3D11:
5180         case RENDERPATH_SOFT:
5181                 break;
5182         }
5183         GL_CullFace(GL_NONE);
5184 }
5185
5186 void R_ResetViewRendering3D(void)
5187 {
5188         DrawQ_Finish();
5189
5190         R_SetupView(true);
5191         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.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(true);
5196         GL_DepthMask(true);
5197         GL_DepthRange(0, 1);
5198         GL_DepthTest(true);
5199         GL_DepthFunc(GL_LEQUAL);
5200         R_EntityMatrix(&identitymatrix);
5201         R_Mesh_ResetTextureState();
5202         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
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(r_refdef.view.cullface_back);
5219 }
5220
5221 /*
5222 ================
5223 R_RenderView_UpdateViewVectors
5224 ================
5225 */
5226 static void R_RenderView_UpdateViewVectors(void)
5227 {
5228         // break apart the view matrix into vectors for various purposes
5229         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5230         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5231         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5232         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5233         // make an inverted copy of the view matrix for tracking sprites
5234         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5235 }
5236
5237 void R_RenderScene(void);
5238 void R_RenderWaterPlanes(void);
5239
5240 static void R_Water_StartFrame(void)
5241 {
5242         int i;
5243         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5244         r_waterstate_waterplane_t *p;
5245
5246         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5247                 return;
5248
5249         switch(vid.renderpath)
5250         {
5251         case RENDERPATH_GL20:
5252         case RENDERPATH_D3D9:
5253         case RENDERPATH_D3D10:
5254         case RENDERPATH_D3D11:
5255         case RENDERPATH_SOFT:
5256         case RENDERPATH_GLES2:
5257                 break;
5258         case RENDERPATH_GL13:
5259         case RENDERPATH_GL11:
5260                 return;
5261         }
5262
5263         // set waterwidth and waterheight to the water resolution that will be
5264         // used (often less than the screen resolution for faster rendering)
5265         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5266         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5267
5268         // calculate desired texture sizes
5269         // can't use water if the card does not support the texture size
5270         if (!r_water.integer || r_showsurfaces.integer)
5271                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5272         else if (vid.support.arb_texture_non_power_of_two)
5273         {
5274                 texturewidth = waterwidth;
5275                 textureheight = waterheight;
5276                 camerawidth = waterwidth;
5277                 cameraheight = waterheight;
5278         }
5279         else
5280         {
5281                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5282                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5283                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5284                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5285         }
5286
5287         // allocate textures as needed
5288         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5289         {
5290                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5291                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5292                 {
5293                         if (p->texture_refraction)
5294                                 R_FreeTexture(p->texture_refraction);
5295                         p->texture_refraction = NULL;
5296                         if (p->texture_reflection)
5297                                 R_FreeTexture(p->texture_reflection);
5298                         p->texture_reflection = NULL;
5299                         if (p->texture_camera)
5300                                 R_FreeTexture(p->texture_camera);
5301                         p->texture_camera = NULL;
5302                 }
5303                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5304                 r_waterstate.texturewidth = texturewidth;
5305                 r_waterstate.textureheight = textureheight;
5306                 r_waterstate.camerawidth = camerawidth;
5307                 r_waterstate.cameraheight = cameraheight;
5308         }
5309
5310         if (r_waterstate.texturewidth)
5311         {
5312                 r_waterstate.enabled = true;
5313
5314                 // when doing a reduced render (HDR) we want to use a smaller area
5315                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5316                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5317
5318                 // set up variables that will be used in shader setup
5319                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5320                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5321                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5322                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5323         }
5324
5325         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5326         r_waterstate.numwaterplanes = 0;
5327 }
5328
5329 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5330 {
5331         int triangleindex, planeindex;
5332         const int *e;
5333         vec3_t vert[3];
5334         vec3_t normal;
5335         vec3_t center;
5336         mplane_t plane;
5337         r_waterstate_waterplane_t *p;
5338         texture_t *t = R_GetCurrentTexture(surface->texture);
5339
5340         // just use the first triangle with a valid normal for any decisions
5341         VectorClear(normal);
5342         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5343         {
5344                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5345                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5346                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5347                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5348                 if (VectorLength2(normal) >= 0.001)
5349                         break;
5350         }
5351
5352         VectorCopy(normal, plane.normal);
5353         VectorNormalize(plane.normal);
5354         plane.dist = DotProduct(vert[0], plane.normal);
5355         PlaneClassify(&plane);
5356         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5357         {
5358                 // skip backfaces (except if nocullface is set)
5359                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5360                         return;
5361                 VectorNegate(plane.normal, plane.normal);
5362                 plane.dist *= -1;
5363                 PlaneClassify(&plane);
5364         }
5365
5366
5367         // find a matching plane if there is one
5368         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5369                 if(p->camera_entity == t->camera_entity)
5370                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5371                                 break;
5372         if (planeindex >= r_waterstate.maxwaterplanes)
5373                 return; // nothing we can do, out of planes
5374
5375         // if this triangle does not fit any known plane rendered this frame, add one
5376         if (planeindex >= r_waterstate.numwaterplanes)
5377         {
5378                 // store the new plane
5379                 r_waterstate.numwaterplanes++;
5380                 p->plane = plane;
5381                 // clear materialflags and pvs
5382                 p->materialflags = 0;
5383                 p->pvsvalid = false;
5384                 p->camera_entity = t->camera_entity;
5385                 VectorCopy(surface->mins, p->mins);
5386                 VectorCopy(surface->maxs, p->maxs);
5387         }
5388         else
5389         {
5390                 // merge mins/maxs
5391                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5392                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5393                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5394                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5395                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5396                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5397         }
5398         // merge this surface's materialflags into the waterplane
5399         p->materialflags |= t->currentmaterialflags;
5400         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5401         {
5402                 // merge this surface's PVS into the waterplane
5403                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5404                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5405                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5406                 {
5407                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5408                         p->pvsvalid = true;
5409                 }
5410         }
5411 }
5412
5413 static void R_Water_ProcessPlanes(void)
5414 {
5415         int myscissor[4];
5416         r_refdef_view_t originalview;
5417         r_refdef_view_t myview;
5418         int planeindex;
5419         r_waterstate_waterplane_t *p;
5420         vec3_t visorigin;
5421
5422         originalview = r_refdef.view;
5423
5424         // make sure enough textures are allocated
5425         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5426         {
5427                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5428                 {
5429                         if (!p->texture_refraction)
5430                                 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);
5431                         if (!p->texture_refraction)
5432                                 goto error;
5433                 }
5434                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5435                 {
5436                         if (!p->texture_camera)
5437                                 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);
5438                         if (!p->texture_camera)
5439                                 goto error;
5440                 }
5441
5442                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5443                 {
5444                         if (!p->texture_reflection)
5445                                 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);
5446                         if (!p->texture_reflection)
5447                                 goto error;
5448                 }
5449         }
5450
5451         // render views
5452         r_refdef.view = originalview;
5453         r_refdef.view.showdebug = false;
5454         r_refdef.view.width = r_waterstate.waterwidth;
5455         r_refdef.view.height = r_waterstate.waterheight;
5456         r_refdef.view.useclipplane = true;
5457         myview = r_refdef.view;
5458         r_waterstate.renderingscene = true;
5459         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5460         {
5461                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5462                 {
5463                         r_refdef.view = myview;
5464                         if(r_water_scissormode.integer)
5465                         {
5466                                 R_SetupView(true);
5467                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5468                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5469                         }
5470
5471                         // render reflected scene and copy into texture
5472                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5473                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5474                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5475                         r_refdef.view.clipplane = p->plane;
5476
5477                         // reverse the cullface settings for this render
5478                         r_refdef.view.cullface_front = GL_FRONT;
5479                         r_refdef.view.cullface_back = GL_BACK;
5480                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5481                         {
5482                                 r_refdef.view.usecustompvs = true;
5483                                 if (p->pvsvalid)
5484                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5485                                 else
5486                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5487                         }
5488
5489                         R_ResetViewRendering3D();
5490                         R_ClearScreen(r_refdef.fogenabled);
5491                         if(r_water_scissormode.integer & 2)
5492                                 R_View_UpdateWithScissor(myscissor);
5493                         else
5494                                 R_View_Update();
5495                         if(r_water_scissormode.integer & 1)
5496                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5497                         R_RenderScene();
5498
5499                         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);
5500                 }
5501
5502                 // render the normal view scene and copy into texture
5503                 // (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)
5504                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5505                 {
5506                         r_refdef.view = myview;
5507                         if(r_water_scissormode.integer)
5508                         {
5509                                 R_SetupView(true);
5510                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5511                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5512                         }
5513
5514                         r_waterstate.renderingrefraction = true;
5515
5516                         r_refdef.view.clipplane = p->plane;
5517                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5518                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5519
5520                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5521                         {
5522                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5523                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5524                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5525                                 R_RenderView_UpdateViewVectors();
5526                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5527                                 {
5528                                         r_refdef.view.usecustompvs = true;
5529                                         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);
5530                                 }
5531                         }
5532
5533                         PlaneClassify(&r_refdef.view.clipplane);
5534
5535                         R_ResetViewRendering3D();
5536                         R_ClearScreen(r_refdef.fogenabled);
5537                         if(r_water_scissormode.integer & 2)
5538                                 R_View_UpdateWithScissor(myscissor);
5539                         else
5540                                 R_View_Update();
5541                         if(r_water_scissormode.integer & 1)
5542                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5543                         R_RenderScene();
5544
5545                         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);
5546                         r_waterstate.renderingrefraction = false;
5547                 }
5548                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5549                 {
5550                         r_refdef.view = myview;
5551
5552                         r_refdef.view.clipplane = p->plane;
5553                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5554                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5555
5556                         r_refdef.view.width = r_waterstate.camerawidth;
5557                         r_refdef.view.height = r_waterstate.cameraheight;
5558                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5559                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5560
5561                         if(p->camera_entity)
5562                         {
5563                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5564                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5565                         }
5566
5567                         // note: all of the view is used for displaying... so
5568                         // there is no use in scissoring
5569
5570                         // reverse the cullface settings for this render
5571                         r_refdef.view.cullface_front = GL_FRONT;
5572                         r_refdef.view.cullface_back = GL_BACK;
5573                         // also reverse the view matrix
5574                         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
5575                         R_RenderView_UpdateViewVectors();
5576                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5577                         {
5578                                 r_refdef.view.usecustompvs = true;
5579                                 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);
5580                         }
5581                         
5582                         // camera needs no clipplane
5583                         r_refdef.view.useclipplane = false;
5584
5585                         PlaneClassify(&r_refdef.view.clipplane);
5586
5587                         R_ResetViewRendering3D();
5588                         R_ClearScreen(r_refdef.fogenabled);
5589                         R_View_Update();
5590                         R_RenderScene();
5591
5592                         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);
5593                         r_waterstate.renderingrefraction = false;
5594                 }
5595
5596         }
5597         r_waterstate.renderingscene = false;
5598         r_refdef.view = originalview;
5599         R_ResetViewRendering3D();
5600         R_ClearScreen(r_refdef.fogenabled);
5601         R_View_Update();
5602         return;
5603 error:
5604         r_refdef.view = originalview;
5605         r_waterstate.renderingscene = false;
5606         Cvar_SetValueQuick(&r_water, 0);
5607         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5608         return;
5609 }
5610
5611 void R_Bloom_StartFrame(void)
5612 {
5613         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5614
5615         switch(vid.renderpath)
5616         {
5617         case RENDERPATH_GL20:
5618         case RENDERPATH_D3D9:
5619         case RENDERPATH_D3D10:
5620         case RENDERPATH_D3D11:
5621         case RENDERPATH_SOFT:
5622         case RENDERPATH_GLES2:
5623                 break;
5624         case RENDERPATH_GL13:
5625         case RENDERPATH_GL11:
5626                 return;
5627         }
5628
5629         // set bloomwidth and bloomheight to the bloom resolution that will be
5630         // used (often less than the screen resolution for faster rendering)
5631         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5632         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5633         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5634         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5635         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5636
5637         // calculate desired texture sizes
5638         if (vid.support.arb_texture_non_power_of_two)
5639         {
5640                 screentexturewidth = r_refdef.view.width;
5641                 screentextureheight = r_refdef.view.height;
5642                 bloomtexturewidth = r_bloomstate.bloomwidth;
5643                 bloomtextureheight = r_bloomstate.bloomheight;
5644         }
5645         else
5646         {
5647                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5648                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5649                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5650                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5651         }
5652
5653         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))
5654         {
5655                 Cvar_SetValueQuick(&r_hdr, 0);
5656                 Cvar_SetValueQuick(&r_bloom, 0);
5657                 Cvar_SetValueQuick(&r_motionblur, 0);
5658                 Cvar_SetValueQuick(&r_damageblur, 0);
5659         }
5660
5661         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)))
5662                 screentexturewidth = screentextureheight = 0;
5663         if (!r_hdr.integer && !r_bloom.integer)
5664                 bloomtexturewidth = bloomtextureheight = 0;
5665
5666         // allocate textures as needed
5667         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5668         {
5669                 if (r_bloomstate.texture_screen)
5670                         R_FreeTexture(r_bloomstate.texture_screen);
5671                 r_bloomstate.texture_screen = NULL;
5672                 r_bloomstate.screentexturewidth = screentexturewidth;
5673                 r_bloomstate.screentextureheight = screentextureheight;
5674                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5675                         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);
5676         }
5677         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5678         {
5679                 if (r_bloomstate.texture_bloom)
5680                         R_FreeTexture(r_bloomstate.texture_bloom);
5681                 r_bloomstate.texture_bloom = NULL;
5682                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5683                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5684                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5685                         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);
5686         }
5687
5688         // when doing a reduced render (HDR) we want to use a smaller area
5689         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5690         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5691         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5692         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5693         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5694
5695         // set up a texcoord array for the full resolution screen image
5696         // (we have to keep this around to copy back during final render)
5697         r_bloomstate.screentexcoord2f[0] = 0;
5698         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5699         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5700         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
5701         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
5702         r_bloomstate.screentexcoord2f[5] = 0;
5703         r_bloomstate.screentexcoord2f[6] = 0;
5704         r_bloomstate.screentexcoord2f[7] = 0;
5705
5706         // set up a texcoord array for the reduced resolution bloom image
5707         // (which will be additive blended over the screen image)
5708         r_bloomstate.bloomtexcoord2f[0] = 0;
5709         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5710         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5711         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5712         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5713         r_bloomstate.bloomtexcoord2f[5] = 0;
5714         r_bloomstate.bloomtexcoord2f[6] = 0;
5715         r_bloomstate.bloomtexcoord2f[7] = 0;
5716
5717         switch(vid.renderpath)
5718         {
5719         case RENDERPATH_GL11:
5720         case RENDERPATH_GL13:
5721         case RENDERPATH_GL20:
5722         case RENDERPATH_SOFT:
5723         case RENDERPATH_GLES2:
5724                 break;
5725         case RENDERPATH_D3D9:
5726         case RENDERPATH_D3D10:
5727         case RENDERPATH_D3D11:
5728                 {
5729                         int i;
5730                         for (i = 0;i < 4;i++)
5731                         {
5732                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5733                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5734                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5735                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5736                         }
5737                 }
5738                 break;
5739         }
5740
5741         if (r_hdr.integer || r_bloom.integer)
5742         {
5743                 r_bloomstate.enabled = true;
5744                 r_bloomstate.hdr = r_hdr.integer != 0;
5745         }
5746
5747         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);
5748 }
5749
5750 void R_Bloom_CopyBloomTexture(float colorscale)
5751 {
5752         r_refdef.stats.bloom++;
5753
5754         // scale down screen texture to the bloom texture size
5755         CHECKGLERROR
5756         R_SetViewport(&r_bloomstate.viewport);
5757         GL_BlendFunc(GL_ONE, GL_ZERO);
5758         GL_Color(colorscale, colorscale, colorscale, 1);
5759         // 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...
5760         switch(vid.renderpath)
5761         {
5762         case RENDERPATH_GL11:
5763         case RENDERPATH_GL13:
5764         case RENDERPATH_GL20:
5765         case RENDERPATH_SOFT:
5766         case RENDERPATH_GLES2:
5767                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5768                 break;
5769         case RENDERPATH_D3D9:
5770         case RENDERPATH_D3D10:
5771         case RENDERPATH_D3D11:
5772                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5773                 break;
5774         }
5775         // TODO: do boxfilter scale-down in shader?
5776         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5777         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5778         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5779
5780         // we now have a bloom image in the framebuffer
5781         // copy it into the bloom image texture for later processing
5782         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);
5783         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5784 }
5785
5786 void R_Bloom_CopyHDRTexture(void)
5787 {
5788         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);
5789         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5790 }
5791
5792 void R_Bloom_MakeTexture(void)
5793 {
5794         int x, range, dir;
5795         float xoffset, yoffset, r, brighten;
5796
5797         r_refdef.stats.bloom++;
5798
5799         R_ResetViewRendering2D();
5800
5801         // we have a bloom image in the framebuffer
5802         CHECKGLERROR
5803         R_SetViewport(&r_bloomstate.viewport);
5804
5805         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5806         {
5807                 x *= 2;
5808                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5809                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5810                 GL_Color(r,r,r,1);
5811                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5812                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5813                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5814                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5815
5816                 // copy the vertically blurred bloom view to a texture
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         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5822         brighten = r_bloom_brighten.value;
5823         if (r_hdr.integer)
5824                 brighten *= r_hdr_range.value;
5825         brighten = sqrt(brighten);
5826         if(range >= 1)
5827                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5828         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5829
5830         for (dir = 0;dir < 2;dir++)
5831         {
5832                 // blend on at multiple vertical offsets to achieve a vertical blur
5833                 // TODO: do offset blends using GLSL
5834                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5835                 GL_BlendFunc(GL_ONE, GL_ZERO);
5836                 for (x = -range;x <= range;x++)
5837                 {
5838                         if (!dir){xoffset = 0;yoffset = x;}
5839                         else {xoffset = x;yoffset = 0;}
5840                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
5841                         yoffset /= (float)r_bloomstate.bloomtextureheight;
5842                         // compute a texcoord array with the specified x and y offset
5843                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5844                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5845                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5846                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5847                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5848                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5849                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5850                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5851                         // this r value looks like a 'dot' particle, fading sharply to
5852                         // black at the edges
5853                         // (probably not realistic but looks good enough)
5854                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5855                         //r = brighten/(range*2+1);
5856                         r = brighten / (range * 2 + 1);
5857                         if(range >= 1)
5858                                 r *= (1 - x*x/(float)(range*range));
5859                         GL_Color(r, r, r, 1);
5860                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5861                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5862                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5863                         GL_BlendFunc(GL_ONE, GL_ONE);
5864                 }
5865
5866                 // copy the vertically blurred bloom view to a texture
5867                 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);
5868                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5869         }
5870 }
5871
5872 void R_HDR_RenderBloomTexture(void)
5873 {
5874         int oldwidth, oldheight;
5875         float oldcolorscale;
5876         qboolean oldwaterstate;
5877
5878         oldwaterstate = r_waterstate.enabled;
5879         oldcolorscale = r_refdef.view.colorscale;
5880         oldwidth = r_refdef.view.width;
5881         oldheight = r_refdef.view.height;
5882         r_refdef.view.width = r_bloomstate.bloomwidth;
5883         r_refdef.view.height = r_bloomstate.bloomheight;
5884
5885         if(r_hdr.integer < 2)
5886                 r_waterstate.enabled = false;
5887
5888         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
5889         // TODO: add exposure compensation features
5890         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5891
5892         r_refdef.view.showdebug = false;
5893         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5894
5895         R_ResetViewRendering3D();
5896
5897         R_ClearScreen(r_refdef.fogenabled);
5898         if (r_timereport_active)
5899                 R_TimeReport("HDRclear");
5900
5901         R_View_Update();
5902         if (r_timereport_active)
5903                 R_TimeReport("visibility");
5904
5905         // only do secondary renders with HDR if r_hdr is 2 or higher
5906         r_waterstate.numwaterplanes = 0;
5907         if (r_waterstate.enabled)
5908                 R_RenderWaterPlanes();
5909
5910         r_refdef.view.showdebug = true;
5911         R_RenderScene();
5912         r_waterstate.numwaterplanes = 0;
5913
5914         R_ResetViewRendering2D();
5915
5916         R_Bloom_CopyHDRTexture();
5917         R_Bloom_MakeTexture();
5918
5919         // restore the view settings
5920         r_waterstate.enabled = oldwaterstate;
5921         r_refdef.view.width = oldwidth;
5922         r_refdef.view.height = oldheight;
5923         r_refdef.view.colorscale = oldcolorscale;
5924
5925         R_ResetViewRendering3D();
5926
5927         R_ClearScreen(r_refdef.fogenabled);
5928         if (r_timereport_active)
5929                 R_TimeReport("viewclear");
5930 }
5931
5932 static void R_BlendView(void)
5933 {
5934         unsigned int permutation;
5935         float uservecs[4][4];
5936
5937         switch (vid.renderpath)
5938         {
5939         case RENDERPATH_GL20:
5940         case RENDERPATH_D3D9:
5941         case RENDERPATH_D3D10:
5942         case RENDERPATH_D3D11:
5943         case RENDERPATH_SOFT:
5944         case RENDERPATH_GLES2:
5945                 permutation =
5946                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5947                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5948                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5949                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5950                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5951
5952                 if (r_bloomstate.texture_screen)
5953                 {
5954                         // make sure the buffer is available
5955                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5956
5957                         R_ResetViewRendering2D();
5958
5959                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5960                         {
5961                                 // declare variables
5962                                 float speed;
5963                                 static float avgspeed;
5964
5965                                 speed = VectorLength(cl.movement_velocity);
5966
5967                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5968                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5969
5970                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5971                                 speed = bound(0, speed, 1);
5972                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5973
5974                                 // calculate values into a standard alpha
5975                                 cl.motionbluralpha = 1 - exp(-
5976                                                 (
5977                                                  (r_motionblur.value * speed / 80)
5978                                                  +
5979                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
5980                                                 )
5981                                                 /
5982                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
5983                                            );
5984
5985                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
5986                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
5987                                 // apply the blur
5988                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
5989                                 {
5990                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5991                                         GL_Color(1, 1, 1, cl.motionbluralpha);
5992                                         switch(vid.renderpath)
5993                                         {
5994                                         case RENDERPATH_GL11:
5995                                         case RENDERPATH_GL13:
5996                                         case RENDERPATH_GL20:
5997                                         case RENDERPATH_SOFT:
5998                                         case RENDERPATH_GLES2:
5999                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6000                                                 break;
6001                                         case RENDERPATH_D3D9:
6002                                         case RENDERPATH_D3D10:
6003                                         case RENDERPATH_D3D11:
6004                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6005                                                 break;
6006                                         }
6007                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6008                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6009                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6010                                 }
6011                         }
6012
6013                         // copy view into the screen texture
6014                         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);
6015                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6016                 }
6017                 else if (!r_bloomstate.texture_bloom)
6018                 {
6019                         // we may still have to do view tint...
6020                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6021                         {
6022                                 // apply a color tint to the whole view
6023                                 R_ResetViewRendering2D();
6024                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6025                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6026                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6027                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6028                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6029                         }
6030                         break; // no screen processing, no bloom, skip it
6031                 }
6032
6033                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6034                 {
6035                         // render simple bloom effect
6036                         // copy the screen and shrink it and darken it for the bloom process
6037                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6038                         // make the bloom texture
6039                         R_Bloom_MakeTexture();
6040                 }
6041
6042 #if _MSC_VER >= 1400
6043 #define sscanf sscanf_s
6044 #endif
6045                 memset(uservecs, 0, sizeof(uservecs));
6046                 if (r_glsl_postprocess_uservec1_enable.integer)
6047                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6048                 if (r_glsl_postprocess_uservec2_enable.integer)
6049                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6050                 if (r_glsl_postprocess_uservec3_enable.integer)
6051                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6052                 if (r_glsl_postprocess_uservec4_enable.integer)
6053                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6054
6055                 R_ResetViewRendering2D();
6056                 GL_Color(1, 1, 1, 1);
6057                 GL_BlendFunc(GL_ONE, GL_ZERO);
6058
6059                 switch(vid.renderpath)
6060                 {
6061                 case RENDERPATH_GL20:
6062                 case RENDERPATH_GLES2:
6063                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6064                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6065                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6066                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6067                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6068                         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]);
6069                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6070                         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]);
6071                         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]);
6072                         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]);
6073                         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]);
6074                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6075                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6076                         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);
6077                         break;
6078                 case RENDERPATH_D3D9:
6079 #ifdef SUPPORTD3D
6080                         // 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...
6081                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6082                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6083                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6084                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6085                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6086                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6087                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6088                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6089                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6090                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6091                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6092                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6093                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6094                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6095 #endif
6096                         break;
6097                 case RENDERPATH_D3D10:
6098                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6099                         break;
6100                 case RENDERPATH_D3D11:
6101                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6102                         break;
6103                 case RENDERPATH_SOFT:
6104                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6105                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6106                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6107                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6108                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6109                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6110                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6111                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6112                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6113                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6114                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6115                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6116                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6117                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6118                         break;
6119                 default:
6120                         break;
6121                 }
6122                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6123                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6124                 break;
6125         case RENDERPATH_GL13:
6126         case RENDERPATH_GL11:
6127                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6128                 {
6129                         // apply a color tint to the whole view
6130                         R_ResetViewRendering2D();
6131                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6132                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6133                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6134                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6135                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6136                 }
6137                 break;
6138         }
6139 }
6140
6141 matrix4x4_t r_waterscrollmatrix;
6142
6143 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6144 {
6145         if (r_refdef.fog_density)
6146         {
6147                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6148                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6149                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6150
6151                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6152                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6153                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6154                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6155
6156                 {
6157                         vec3_t fogvec;
6158                         VectorCopy(r_refdef.fogcolor, fogvec);
6159                         //   color.rgb *= ContrastBoost * SceneBrightness;
6160                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6161                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6162                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6163                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6164                 }
6165         }
6166 }
6167
6168 void R_UpdateVariables(void)
6169 {
6170         R_Textures_Frame();
6171
6172         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6173
6174         r_refdef.farclip = r_farclip_base.value;
6175         if (r_refdef.scene.worldmodel)
6176                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6177         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6178
6179         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6180                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6181         r_refdef.polygonfactor = 0;
6182         r_refdef.polygonoffset = 0;
6183         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6184         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6185
6186         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6187         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6188         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6189         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6190         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6191         if (FAKELIGHT_ENABLED)
6192         {
6193                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6194         }
6195         if (r_showsurfaces.integer)
6196         {
6197                 r_refdef.scene.rtworld = false;
6198                 r_refdef.scene.rtworldshadows = false;
6199                 r_refdef.scene.rtdlight = false;
6200                 r_refdef.scene.rtdlightshadows = false;
6201                 r_refdef.lightmapintensity = 0;
6202         }
6203
6204         if (gamemode == GAME_NEHAHRA)
6205         {
6206                 if (gl_fogenable.integer)
6207                 {
6208                         r_refdef.oldgl_fogenable = true;
6209                         r_refdef.fog_density = gl_fogdensity.value;
6210                         r_refdef.fog_red = gl_fogred.value;
6211                         r_refdef.fog_green = gl_foggreen.value;
6212                         r_refdef.fog_blue = gl_fogblue.value;
6213                         r_refdef.fog_alpha = 1;
6214                         r_refdef.fog_start = 0;
6215                         r_refdef.fog_end = gl_skyclip.value;
6216                         r_refdef.fog_height = 1<<30;
6217                         r_refdef.fog_fadedepth = 128;
6218                 }
6219                 else if (r_refdef.oldgl_fogenable)
6220                 {
6221                         r_refdef.oldgl_fogenable = false;
6222                         r_refdef.fog_density = 0;
6223                         r_refdef.fog_red = 0;
6224                         r_refdef.fog_green = 0;
6225                         r_refdef.fog_blue = 0;
6226                         r_refdef.fog_alpha = 0;
6227                         r_refdef.fog_start = 0;
6228                         r_refdef.fog_end = 0;
6229                         r_refdef.fog_height = 1<<30;
6230                         r_refdef.fog_fadedepth = 128;
6231                 }
6232         }
6233
6234         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6235         r_refdef.fog_start = max(0, r_refdef.fog_start);
6236         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6237
6238         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6239
6240         if (r_refdef.fog_density && r_drawfog.integer)
6241         {
6242                 r_refdef.fogenabled = true;
6243                 // this is the point where the fog reaches 0.9986 alpha, which we
6244                 // consider a good enough cutoff point for the texture
6245                 // (0.9986 * 256 == 255.6)
6246                 if (r_fog_exp2.integer)
6247                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6248                 else
6249                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6250                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6251                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6252                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6253                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6254                         R_BuildFogHeightTexture();
6255                 // fog color was already set
6256                 // update the fog texture
6257                 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)
6258                         R_BuildFogTexture();
6259                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6260                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6261         }
6262         else
6263                 r_refdef.fogenabled = false;
6264
6265         switch(vid.renderpath)
6266         {
6267         case RENDERPATH_GL20:
6268         case RENDERPATH_D3D9:
6269         case RENDERPATH_D3D10:
6270         case RENDERPATH_D3D11:
6271         case RENDERPATH_SOFT:
6272         case RENDERPATH_GLES2:
6273                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6274                 {
6275                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6276                         {
6277                                 // build GLSL gamma texture
6278 #define RAMPWIDTH 256
6279                                 unsigned short ramp[RAMPWIDTH * 3];
6280                                 unsigned char rampbgr[RAMPWIDTH][4];
6281                                 int i;
6282
6283                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6284
6285                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6286                                 for(i = 0; i < RAMPWIDTH; ++i)
6287                                 {
6288                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6289                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6290                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6291                                         rampbgr[i][3] = 0;
6292                                 }
6293                                 if (r_texture_gammaramps)
6294                                 {
6295                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6296                                 }
6297                                 else
6298                                 {
6299                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6300                                 }
6301                         }
6302                 }
6303                 else
6304                 {
6305                         // remove GLSL gamma texture
6306                 }
6307                 break;
6308         case RENDERPATH_GL13:
6309         case RENDERPATH_GL11:
6310                 break;
6311         }
6312 }
6313
6314 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6315 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6316 /*
6317 ================
6318 R_SelectScene
6319 ================
6320 */
6321 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6322         if( scenetype != r_currentscenetype ) {
6323                 // store the old scenetype
6324                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6325                 r_currentscenetype = scenetype;
6326                 // move in the new scene
6327                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6328         }
6329 }
6330
6331 /*
6332 ================
6333 R_GetScenePointer
6334 ================
6335 */
6336 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6337 {
6338         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6339         if( scenetype == r_currentscenetype ) {
6340                 return &r_refdef.scene;
6341         } else {
6342                 return &r_scenes_store[ scenetype ];
6343         }
6344 }
6345
6346 /*
6347 ================
6348 R_RenderView
6349 ================
6350 */
6351 int dpsoftrast_test;
6352 void R_RenderView(void)
6353 {
6354         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6355
6356         dpsoftrast_test = r_test.integer;
6357
6358         if (r_timereport_active)
6359                 R_TimeReport("start");
6360         r_textureframe++; // used only by R_GetCurrentTexture
6361         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6362
6363         if(R_CompileShader_CheckStaticParms())
6364                 R_GLSL_Restart_f();
6365
6366         if (!r_drawentities.integer)
6367                 r_refdef.scene.numentities = 0;
6368
6369         R_AnimCache_ClearCache();
6370         R_FrameData_NewFrame();
6371
6372         /* adjust for stereo display */
6373         if(R_Stereo_Active())
6374         {
6375                 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);
6376                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6377         }
6378
6379         if (r_refdef.view.isoverlay)
6380         {
6381                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6382                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6383                 R_TimeReport("depthclear");
6384
6385                 r_refdef.view.showdebug = false;
6386
6387                 r_waterstate.enabled = false;
6388                 r_waterstate.numwaterplanes = 0;
6389
6390                 R_RenderScene();
6391
6392                 r_refdef.view.matrix = originalmatrix;
6393
6394                 CHECKGLERROR
6395                 return;
6396         }
6397
6398         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6399         {
6400                 r_refdef.view.matrix = originalmatrix;
6401                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6402         }
6403
6404         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6405
6406         R_RenderView_UpdateViewVectors();
6407
6408         R_Shadow_UpdateWorldLightSelection();
6409
6410         R_Bloom_StartFrame();
6411         R_Water_StartFrame();
6412
6413         CHECKGLERROR
6414         if (r_timereport_active)
6415                 R_TimeReport("viewsetup");
6416
6417         R_ResetViewRendering3D();
6418
6419         if (r_refdef.view.clear || r_refdef.fogenabled)
6420         {
6421                 R_ClearScreen(r_refdef.fogenabled);
6422                 if (r_timereport_active)
6423                         R_TimeReport("viewclear");
6424         }
6425         r_refdef.view.clear = true;
6426
6427         // this produces a bloom texture to be used in R_BlendView() later
6428         if (r_hdr.integer && r_bloomstate.bloomwidth)
6429         {
6430                 R_HDR_RenderBloomTexture();
6431                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6432                 r_textureframe++; // used only by R_GetCurrentTexture
6433         }
6434
6435         r_refdef.view.showdebug = true;
6436
6437         R_View_Update();
6438         if (r_timereport_active)
6439                 R_TimeReport("visibility");
6440
6441         r_waterstate.numwaterplanes = 0;
6442         if (r_waterstate.enabled)
6443                 R_RenderWaterPlanes();
6444
6445         R_RenderScene();
6446         r_waterstate.numwaterplanes = 0;
6447
6448         R_BlendView();
6449         if (r_timereport_active)
6450                 R_TimeReport("blendview");
6451
6452         GL_Scissor(0, 0, vid.width, vid.height);
6453         GL_ScissorTest(false);
6454
6455         r_refdef.view.matrix = originalmatrix;
6456
6457         CHECKGLERROR
6458 }
6459
6460 void R_RenderWaterPlanes(void)
6461 {
6462         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6463         {
6464                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6465                 if (r_timereport_active)
6466                         R_TimeReport("waterworld");
6467         }
6468
6469         // don't let sound skip if going slow
6470         if (r_refdef.scene.extraupdate)
6471                 S_ExtraUpdate ();
6472
6473         R_DrawModelsAddWaterPlanes();
6474         if (r_timereport_active)
6475                 R_TimeReport("watermodels");
6476
6477         if (r_waterstate.numwaterplanes)
6478         {
6479                 R_Water_ProcessPlanes();
6480                 if (r_timereport_active)
6481                         R_TimeReport("waterscenes");
6482         }
6483 }
6484
6485 extern void R_DrawLightningBeams (void);
6486 extern void VM_CL_AddPolygonsToMeshQueue (void);
6487 extern void R_DrawPortals (void);
6488 extern cvar_t cl_locs_show;
6489 static void R_DrawLocs(void);
6490 static void R_DrawEntityBBoxes(void);
6491 static void R_DrawModelDecals(void);
6492 extern void R_DrawModelShadows(void);
6493 extern void R_DrawModelShadowMaps(void);
6494 extern cvar_t cl_decals_newsystem;
6495 extern qboolean r_shadow_usingdeferredprepass;
6496 void R_RenderScene(void)
6497 {
6498         qboolean shadowmapping = false;
6499
6500         if (r_timereport_active)
6501                 R_TimeReport("beginscene");
6502
6503         r_refdef.stats.renders++;
6504
6505         R_UpdateFogColor();
6506
6507         // don't let sound skip if going slow
6508         if (r_refdef.scene.extraupdate)
6509                 S_ExtraUpdate ();
6510
6511         R_MeshQueue_BeginScene();
6512
6513         R_SkyStartFrame();
6514
6515         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);
6516
6517         if (r_timereport_active)
6518                 R_TimeReport("skystartframe");
6519
6520         if (cl.csqc_vidvars.drawworld)
6521         {
6522                 // don't let sound skip if going slow
6523                 if (r_refdef.scene.extraupdate)
6524                         S_ExtraUpdate ();
6525
6526                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6527                 {
6528                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6529                         if (r_timereport_active)
6530                                 R_TimeReport("worldsky");
6531                 }
6532
6533                 if (R_DrawBrushModelsSky() && r_timereport_active)
6534                         R_TimeReport("bmodelsky");
6535
6536                 if (skyrendermasked && skyrenderlater)
6537                 {
6538                         // we have to force off the water clipping plane while rendering sky
6539                         R_SetupView(false);
6540                         R_Sky();
6541                         R_SetupView(true);
6542                         if (r_timereport_active)
6543                                 R_TimeReport("sky");
6544                 }
6545         }
6546
6547         R_AnimCache_CacheVisibleEntities();
6548         if (r_timereport_active)
6549                 R_TimeReport("animation");
6550
6551         R_Shadow_PrepareLights();
6552         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6553                 R_Shadow_PrepareModelShadows();
6554         if (r_timereport_active)
6555                 R_TimeReport("preparelights");
6556
6557         if (R_Shadow_ShadowMappingEnabled())
6558                 shadowmapping = true;
6559
6560         if (r_shadow_usingdeferredprepass)
6561                 R_Shadow_DrawPrepass();
6562
6563         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6564         {
6565                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6566                 if (r_timereport_active)
6567                         R_TimeReport("worlddepth");
6568         }
6569         if (r_depthfirst.integer >= 2)
6570         {
6571                 R_DrawModelsDepth();
6572                 if (r_timereport_active)
6573                         R_TimeReport("modeldepth");
6574         }
6575
6576         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6577         {
6578                 R_DrawModelShadowMaps();
6579                 R_ResetViewRendering3D();
6580                 // don't let sound skip if going slow
6581                 if (r_refdef.scene.extraupdate)
6582                         S_ExtraUpdate ();
6583         }
6584
6585         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6586         {
6587                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6588                 if (r_timereport_active)
6589                         R_TimeReport("world");
6590         }
6591
6592         // don't let sound skip if going slow
6593         if (r_refdef.scene.extraupdate)
6594                 S_ExtraUpdate ();
6595
6596         R_DrawModels();
6597         if (r_timereport_active)
6598                 R_TimeReport("models");
6599
6600         // don't let sound skip if going slow
6601         if (r_refdef.scene.extraupdate)
6602                 S_ExtraUpdate ();
6603
6604         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6605         {
6606                 R_DrawModelShadows();
6607                 R_ResetViewRendering3D();
6608                 // don't let sound skip if going slow
6609                 if (r_refdef.scene.extraupdate)
6610                         S_ExtraUpdate ();
6611         }
6612
6613         if (!r_shadow_usingdeferredprepass)
6614         {
6615                 R_Shadow_DrawLights();
6616                 if (r_timereport_active)
6617                         R_TimeReport("rtlights");
6618         }
6619
6620         // don't let sound skip if going slow
6621         if (r_refdef.scene.extraupdate)
6622                 S_ExtraUpdate ();
6623
6624         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6625         {
6626                 R_DrawModelShadows();
6627                 R_ResetViewRendering3D();
6628                 // don't let sound skip if going slow
6629                 if (r_refdef.scene.extraupdate)
6630                         S_ExtraUpdate ();
6631         }
6632
6633         if (cl.csqc_vidvars.drawworld)
6634         {
6635                 if (cl_decals_newsystem.integer)
6636                 {
6637                         R_DrawModelDecals();
6638                         if (r_timereport_active)
6639                                 R_TimeReport("modeldecals");
6640                 }
6641                 else
6642                 {
6643                         R_DrawDecals();
6644                         if (r_timereport_active)
6645                                 R_TimeReport("decals");
6646                 }
6647
6648                 R_DrawParticles();
6649                 if (r_timereport_active)
6650                         R_TimeReport("particles");
6651
6652                 R_DrawExplosions();
6653                 if (r_timereport_active)
6654                         R_TimeReport("explosions");
6655
6656                 R_DrawLightningBeams();
6657                 if (r_timereport_active)
6658                         R_TimeReport("lightning");
6659         }
6660
6661         VM_CL_AddPolygonsToMeshQueue();
6662
6663         if (r_refdef.view.showdebug)
6664         {
6665                 if (cl_locs_show.integer)
6666                 {
6667                         R_DrawLocs();
6668                         if (r_timereport_active)
6669                                 R_TimeReport("showlocs");
6670                 }
6671
6672                 if (r_drawportals.integer)
6673                 {
6674                         R_DrawPortals();
6675                         if (r_timereport_active)
6676                                 R_TimeReport("portals");
6677                 }
6678
6679                 if (r_showbboxes.value > 0)
6680                 {
6681                         R_DrawEntityBBoxes();
6682                         if (r_timereport_active)
6683                                 R_TimeReport("bboxes");
6684                 }
6685         }
6686
6687         R_MeshQueue_RenderTransparent();
6688         if (r_timereport_active)
6689                 R_TimeReport("drawtrans");
6690
6691         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))
6692         {
6693                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6694                 if (r_timereport_active)
6695                         R_TimeReport("worlddebug");
6696                 R_DrawModelsDebug();
6697                 if (r_timereport_active)
6698                         R_TimeReport("modeldebug");
6699         }
6700
6701         if (cl.csqc_vidvars.drawworld)
6702         {
6703                 R_Shadow_DrawCoronas();
6704                 if (r_timereport_active)
6705                         R_TimeReport("coronas");
6706         }
6707
6708 #if 0
6709         {
6710                 GL_DepthTest(false);
6711                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6712                 GL_Color(1, 1, 1, 1);
6713                 qglBegin(GL_POLYGON);
6714                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6715                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6716                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6717                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6718                 qglEnd();
6719                 qglBegin(GL_POLYGON);
6720                 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]);
6721                 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]);
6722                 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]);
6723                 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]);
6724                 qglEnd();
6725                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6726         }
6727 #endif
6728
6729         // don't let sound skip if going slow
6730         if (r_refdef.scene.extraupdate)
6731                 S_ExtraUpdate ();
6732
6733         R_ResetViewRendering2D();
6734 }
6735
6736 static const unsigned short bboxelements[36] =
6737 {
6738         5, 1, 3, 5, 3, 7,
6739         6, 2, 0, 6, 0, 4,
6740         7, 3, 2, 7, 2, 6,
6741         4, 0, 1, 4, 1, 5,
6742         4, 5, 7, 4, 7, 6,
6743         1, 0, 2, 1, 2, 3,
6744 };
6745
6746 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6747 {
6748         int i;
6749         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6750
6751         RSurf_ActiveWorldEntity();
6752
6753         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6754         GL_DepthMask(false);
6755         GL_DepthRange(0, 1);
6756         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6757 //      R_Mesh_ResetTextureState();
6758
6759         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6760         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6761         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6762         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6763         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6764         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6765         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6766         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6767         R_FillColors(color4f, 8, cr, cg, cb, ca);
6768         if (r_refdef.fogenabled)
6769         {
6770                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6771                 {
6772                         f1 = RSurf_FogVertex(v);
6773                         f2 = 1 - f1;
6774                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6775                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6776                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6777                 }
6778         }
6779         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6780         R_Mesh_ResetTextureState();
6781         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6782         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6783 }
6784
6785 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6786 {
6787         int i;
6788         float color[4];
6789         prvm_edict_t *edict;
6790         prvm_prog_t *prog_save = prog;
6791
6792         // this function draws bounding boxes of server entities
6793         if (!sv.active)
6794                 return;
6795
6796         GL_CullFace(GL_NONE);
6797         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6798
6799         prog = 0;
6800         SV_VM_Begin();
6801         for (i = 0;i < numsurfaces;i++)
6802         {
6803                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6804                 switch ((int)edict->fields.server->solid)
6805                 {
6806                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6807                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
6808                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
6809                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6810                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
6811                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
6812                 }
6813                 color[3] *= r_showbboxes.value;
6814                 color[3] = bound(0, color[3], 1);
6815                 GL_DepthTest(!r_showdisabledepthtest.integer);
6816                 GL_CullFace(r_refdef.view.cullface_front);
6817                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6818         }
6819         SV_VM_End();
6820         prog = prog_save;
6821 }
6822
6823 static void R_DrawEntityBBoxes(void)
6824 {
6825         int i;
6826         prvm_edict_t *edict;
6827         vec3_t center;
6828         prvm_prog_t *prog_save = prog;
6829
6830         // this function draws bounding boxes of server entities
6831         if (!sv.active)
6832                 return;
6833
6834         prog = 0;
6835         SV_VM_Begin();
6836         for (i = 0;i < prog->num_edicts;i++)
6837         {
6838                 edict = PRVM_EDICT_NUM(i);
6839                 if (edict->priv.server->free)
6840                         continue;
6841                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6842                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6843                         continue;
6844                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6845                         continue;
6846                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6847                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6848         }
6849         SV_VM_End();
6850         prog = prog_save;
6851 }
6852
6853 static const int nomodelelement3i[24] =
6854 {
6855         5, 2, 0,
6856         5, 1, 2,
6857         5, 0, 3,
6858         5, 3, 1,
6859         0, 2, 4,
6860         2, 1, 4,
6861         3, 0, 4,
6862         1, 3, 4
6863 };
6864
6865 static const unsigned short nomodelelement3s[24] =
6866 {
6867         5, 2, 0,
6868         5, 1, 2,
6869         5, 0, 3,
6870         5, 3, 1,
6871         0, 2, 4,
6872         2, 1, 4,
6873         3, 0, 4,
6874         1, 3, 4
6875 };
6876
6877 static const float nomodelvertex3f[6*3] =
6878 {
6879         -16,   0,   0,
6880          16,   0,   0,
6881           0, -16,   0,
6882           0,  16,   0,
6883           0,   0, -16,
6884           0,   0,  16
6885 };
6886
6887 static const float nomodelcolor4f[6*4] =
6888 {
6889         0.0f, 0.0f, 0.5f, 1.0f,
6890         0.0f, 0.0f, 0.5f, 1.0f,
6891         0.0f, 0.5f, 0.0f, 1.0f,
6892         0.0f, 0.5f, 0.0f, 1.0f,
6893         0.5f, 0.0f, 0.0f, 1.0f,
6894         0.5f, 0.0f, 0.0f, 1.0f
6895 };
6896
6897 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6898 {
6899         int i;
6900         float f1, f2, *c;
6901         float color4f[6*4];
6902
6903         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);
6904
6905         // this is only called once per entity so numsurfaces is always 1, and
6906         // surfacelist is always {0}, so this code does not handle batches
6907
6908         if (rsurface.ent_flags & RENDER_ADDITIVE)
6909         {
6910                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6911                 GL_DepthMask(false);
6912         }
6913         else if (rsurface.colormod[3] < 1)
6914         {
6915                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6916                 GL_DepthMask(false);
6917         }
6918         else
6919         {
6920                 GL_BlendFunc(GL_ONE, GL_ZERO);
6921                 GL_DepthMask(true);
6922         }
6923         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6924         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6925         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6926         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6927         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6928         for (i = 0, c = color4f;i < 6;i++, c += 4)
6929         {
6930                 c[0] *= rsurface.colormod[0];
6931                 c[1] *= rsurface.colormod[1];
6932                 c[2] *= rsurface.colormod[2];
6933                 c[3] *= rsurface.colormod[3];
6934         }
6935         if (r_refdef.fogenabled)
6936         {
6937                 for (i = 0, c = color4f;i < 6;i++, c += 4)
6938                 {
6939                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6940                         f2 = 1 - f1;
6941                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6942                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6943                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6944                 }
6945         }
6946 //      R_Mesh_ResetTextureState();
6947         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6948         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6949         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6950 }
6951
6952 void R_DrawNoModel(entity_render_t *ent)
6953 {
6954         vec3_t org;
6955         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6956         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6957                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6958         else
6959                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6960 }
6961
6962 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6963 {
6964         vec3_t right1, right2, diff, normal;
6965
6966         VectorSubtract (org2, org1, normal);
6967
6968         // calculate 'right' vector for start
6969         VectorSubtract (r_refdef.view.origin, org1, diff);
6970         CrossProduct (normal, diff, right1);
6971         VectorNormalize (right1);
6972
6973         // calculate 'right' vector for end
6974         VectorSubtract (r_refdef.view.origin, org2, diff);
6975         CrossProduct (normal, diff, right2);
6976         VectorNormalize (right2);
6977
6978         vert[ 0] = org1[0] + width * right1[0];
6979         vert[ 1] = org1[1] + width * right1[1];
6980         vert[ 2] = org1[2] + width * right1[2];
6981         vert[ 3] = org1[0] - width * right1[0];
6982         vert[ 4] = org1[1] - width * right1[1];
6983         vert[ 5] = org1[2] - width * right1[2];
6984         vert[ 6] = org2[0] - width * right2[0];
6985         vert[ 7] = org2[1] - width * right2[1];
6986         vert[ 8] = org2[2] - width * right2[2];
6987         vert[ 9] = org2[0] + width * right2[0];
6988         vert[10] = org2[1] + width * right2[1];
6989         vert[11] = org2[2] + width * right2[2];
6990 }
6991
6992 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)
6993 {
6994         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
6995         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
6996         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
6997         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
6998         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
6999         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7000         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7001         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7002         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7003         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7004         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7005         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7006 }
7007
7008 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7009 {
7010         int i;
7011         float *vertex3f;
7012         float v[3];
7013         VectorSet(v, x, y, z);
7014         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7015                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7016                         break;
7017         if (i == mesh->numvertices)
7018         {
7019                 if (mesh->numvertices < mesh->maxvertices)
7020                 {
7021                         VectorCopy(v, vertex3f);
7022                         mesh->numvertices++;
7023                 }
7024                 return mesh->numvertices;
7025         }
7026         else
7027                 return i;
7028 }
7029
7030 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7031 {
7032         int i;
7033         int *e, element[3];
7034         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7035         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7036         e = mesh->element3i + mesh->numtriangles * 3;
7037         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7038         {
7039                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7040                 if (mesh->numtriangles < mesh->maxtriangles)
7041                 {
7042                         *e++ = element[0];
7043                         *e++ = element[1];
7044                         *e++ = element[2];
7045                         mesh->numtriangles++;
7046                 }
7047                 element[1] = element[2];
7048         }
7049 }
7050
7051 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7052 {
7053         int i;
7054         int *e, element[3];
7055         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7056         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7057         e = mesh->element3i + mesh->numtriangles * 3;
7058         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7059         {
7060                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7061                 if (mesh->numtriangles < mesh->maxtriangles)
7062                 {
7063                         *e++ = element[0];
7064                         *e++ = element[1];
7065                         *e++ = element[2];
7066                         mesh->numtriangles++;
7067                 }
7068                 element[1] = element[2];
7069         }
7070 }
7071
7072 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7073 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7074 {
7075         int planenum, planenum2;
7076         int w;
7077         int tempnumpoints;
7078         mplane_t *plane, *plane2;
7079         double maxdist;
7080         double temppoints[2][256*3];
7081         // figure out how large a bounding box we need to properly compute this brush
7082         maxdist = 0;
7083         for (w = 0;w < numplanes;w++)
7084                 maxdist = max(maxdist, fabs(planes[w].dist));
7085         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7086         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7087         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7088         {
7089                 w = 0;
7090                 tempnumpoints = 4;
7091                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7092                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7093                 {
7094                         if (planenum2 == planenum)
7095                                 continue;
7096                         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);
7097                         w = !w;
7098                 }
7099                 if (tempnumpoints < 3)
7100                         continue;
7101                 // generate elements forming a triangle fan for this polygon
7102                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7103         }
7104 }
7105
7106 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)
7107 {
7108         texturelayer_t *layer;
7109         layer = t->currentlayers + t->currentnumlayers++;
7110         layer->type = type;
7111         layer->depthmask = depthmask;
7112         layer->blendfunc1 = blendfunc1;
7113         layer->blendfunc2 = blendfunc2;
7114         layer->texture = texture;
7115         layer->texmatrix = *matrix;
7116         layer->color[0] = r;
7117         layer->color[1] = g;
7118         layer->color[2] = b;
7119         layer->color[3] = a;
7120 }
7121
7122 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7123 {
7124         if(parms[0] == 0 && parms[1] == 0)
7125                 return false;
7126         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7127                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7128                         return false;
7129         return true;
7130 }
7131
7132 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7133 {
7134         double index, f;
7135         index = parms[2] + r_refdef.scene.time * parms[3];
7136         index -= floor(index);
7137         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7138         {
7139         default:
7140         case Q3WAVEFUNC_NONE:
7141         case Q3WAVEFUNC_NOISE:
7142         case Q3WAVEFUNC_COUNT:
7143                 f = 0;
7144                 break;
7145         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7146         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7147         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7148         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7149         case Q3WAVEFUNC_TRIANGLE:
7150                 index *= 4;
7151                 f = index - floor(index);
7152                 if (index < 1)
7153                         f = f;
7154                 else if (index < 2)
7155                         f = 1 - f;
7156                 else if (index < 3)
7157                         f = -f;
7158                 else
7159                         f = -(1 - f);
7160                 break;
7161         }
7162         f = parms[0] + parms[1] * f;
7163         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7164                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7165         return (float) f;
7166 }
7167
7168 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7169 {
7170         int w, h, idx;
7171         float f;
7172         float tcmat[12];
7173         matrix4x4_t matrix, temp;
7174         switch(tcmod->tcmod)
7175         {
7176                 case Q3TCMOD_COUNT:
7177                 case Q3TCMOD_NONE:
7178                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7179                                 matrix = r_waterscrollmatrix;
7180                         else
7181                                 matrix = identitymatrix;
7182                         break;
7183                 case Q3TCMOD_ENTITYTRANSLATE:
7184                         // this is used in Q3 to allow the gamecode to control texcoord
7185                         // scrolling on the entity, which is not supported in darkplaces yet.
7186                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7187                         break;
7188                 case Q3TCMOD_ROTATE:
7189                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7190                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7191                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7192                         break;
7193                 case Q3TCMOD_SCALE:
7194                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7195                         break;
7196                 case Q3TCMOD_SCROLL:
7197                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7198                         break;
7199                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7200                         w = (int) tcmod->parms[0];
7201                         h = (int) tcmod->parms[1];
7202                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7203                         f = f - floor(f);
7204                         idx = (int) floor(f * w * h);
7205                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7206                         break;
7207                 case Q3TCMOD_STRETCH:
7208                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7209                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7210                         break;
7211                 case Q3TCMOD_TRANSFORM:
7212                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7213                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7214                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7215                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7216                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7217                         break;
7218                 case Q3TCMOD_TURBULENT:
7219                         // this is handled in the RSurf_PrepareVertices function
7220                         matrix = identitymatrix;
7221                         break;
7222         }
7223         temp = *texmatrix;
7224         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7225 }
7226
7227 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7228 {
7229         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7230         char name[MAX_QPATH];
7231         skinframe_t *skinframe;
7232         unsigned char pixels[296*194];
7233         strlcpy(cache->name, skinname, sizeof(cache->name));
7234         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7235         if (developer_loading.integer)
7236                 Con_Printf("loading %s\n", name);
7237         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7238         if (!skinframe || !skinframe->base)
7239         {
7240                 unsigned char *f;
7241                 fs_offset_t filesize;
7242                 skinframe = NULL;
7243                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7244                 if (f)
7245                 {
7246                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7247                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7248                         Mem_Free(f);
7249                 }
7250         }
7251         cache->skinframe = skinframe;
7252 }
7253
7254 texture_t *R_GetCurrentTexture(texture_t *t)
7255 {
7256         int i;
7257         const entity_render_t *ent = rsurface.entity;
7258         dp_model_t *model = ent->model;
7259         q3shaderinfo_layer_tcmod_t *tcmod;
7260
7261         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7262                 return t->currentframe;
7263         t->update_lastrenderframe = r_textureframe;
7264         t->update_lastrenderentity = (void *)ent;
7265
7266         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7267                 t->camera_entity = ent->entitynumber;
7268         else
7269                 t->camera_entity = 0;
7270
7271         // switch to an alternate material if this is a q1bsp animated material
7272         {
7273                 texture_t *texture = t;
7274                 int s = rsurface.ent_skinnum;
7275                 if ((unsigned int)s >= (unsigned int)model->numskins)
7276                         s = 0;
7277                 if (model->skinscenes)
7278                 {
7279                         if (model->skinscenes[s].framecount > 1)
7280                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7281                         else
7282                                 s = model->skinscenes[s].firstframe;
7283                 }
7284                 if (s > 0)
7285                         t = t + s * model->num_surfaces;
7286                 if (t->animated)
7287                 {
7288                         // use an alternate animation if the entity's frame is not 0,
7289                         // and only if the texture has an alternate animation
7290                         if (rsurface.ent_alttextures && t->anim_total[1])
7291                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7292                         else
7293                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7294                 }
7295                 texture->currentframe = t;
7296         }
7297
7298         // update currentskinframe to be a qw skin or animation frame
7299         if (rsurface.ent_qwskin >= 0)
7300         {
7301                 i = rsurface.ent_qwskin;
7302                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7303                 {
7304                         r_qwskincache_size = cl.maxclients;
7305                         if (r_qwskincache)
7306                                 Mem_Free(r_qwskincache);
7307                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7308                 }
7309                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7310                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7311                 t->currentskinframe = r_qwskincache[i].skinframe;
7312                 if (t->currentskinframe == NULL)
7313                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7314         }
7315         else if (t->numskinframes >= 2)
7316                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7317         if (t->backgroundnumskinframes >= 2)
7318                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7319
7320         t->currentmaterialflags = t->basematerialflags;
7321         t->currentalpha = rsurface.colormod[3];
7322         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7323                 t->currentalpha *= r_wateralpha.value;
7324         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7325                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7326         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7327                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7328         if (!(rsurface.ent_flags & RENDER_LIGHT))
7329                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7330         else if (FAKELIGHT_ENABLED)
7331         {
7332                         // no modellight if using fakelight for the map
7333         }
7334         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7335         {
7336                 // pick a model lighting mode
7337                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7338                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7339                 else
7340                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7341         }
7342         if (rsurface.ent_flags & RENDER_ADDITIVE)
7343                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7344         else if (t->currentalpha < 1)
7345                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7346         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7347                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7348         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7349                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7350         if (t->backgroundnumskinframes)
7351                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7352         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7353         {
7354                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7355                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7356         }
7357         else
7358                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7359         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7360                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7361
7362         // there is no tcmod
7363         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7364         {
7365                 t->currenttexmatrix = r_waterscrollmatrix;
7366                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7367         }
7368         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7369         {
7370                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7371                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7372         }
7373
7374         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7375                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7376         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7377                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7378
7379         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7380         if (t->currentskinframe->qpixels)
7381                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7382         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7383         if (!t->basetexture)
7384                 t->basetexture = r_texture_notexture;
7385         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7386         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7387         t->nmaptexture = t->currentskinframe->nmap;
7388         if (!t->nmaptexture)
7389                 t->nmaptexture = r_texture_blanknormalmap;
7390         t->glosstexture = r_texture_black;
7391         t->glowtexture = t->currentskinframe->glow;
7392         t->fogtexture = t->currentskinframe->fog;
7393         t->reflectmasktexture = t->currentskinframe->reflect;
7394         if (t->backgroundnumskinframes)
7395         {
7396                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7397                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7398                 t->backgroundglosstexture = r_texture_black;
7399                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7400                 if (!t->backgroundnmaptexture)
7401                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7402         }
7403         else
7404         {
7405                 t->backgroundbasetexture = r_texture_white;
7406                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7407                 t->backgroundglosstexture = r_texture_black;
7408                 t->backgroundglowtexture = NULL;
7409         }
7410         t->specularpower = r_shadow_glossexponent.value;
7411         // TODO: store reference values for these in the texture?
7412         t->specularscale = 0;
7413         if (r_shadow_gloss.integer > 0)
7414         {
7415                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7416                 {
7417                         if (r_shadow_glossintensity.value > 0)
7418                         {
7419                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7420                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7421                                 t->specularscale = r_shadow_glossintensity.value;
7422                         }
7423                 }
7424                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7425                 {
7426                         t->glosstexture = r_texture_white;
7427                         t->backgroundglosstexture = r_texture_white;
7428                         t->specularscale = r_shadow_gloss2intensity.value;
7429                         t->specularpower = r_shadow_gloss2exponent.value;
7430                 }
7431         }
7432         t->specularscale *= t->specularscalemod;
7433         t->specularpower *= t->specularpowermod;
7434
7435         // lightmaps mode looks bad with dlights using actual texturing, so turn
7436         // off the colormap and glossmap, but leave the normalmap on as it still
7437         // accurately represents the shading involved
7438         if (gl_lightmaps.integer)
7439         {
7440                 t->basetexture = r_texture_grey128;
7441                 t->pantstexture = r_texture_black;
7442                 t->shirttexture = r_texture_black;
7443                 t->nmaptexture = r_texture_blanknormalmap;
7444                 t->glosstexture = r_texture_black;
7445                 t->glowtexture = NULL;
7446                 t->fogtexture = NULL;
7447                 t->reflectmasktexture = NULL;
7448                 t->backgroundbasetexture = NULL;
7449                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7450                 t->backgroundglosstexture = r_texture_black;
7451                 t->backgroundglowtexture = NULL;
7452                 t->specularscale = 0;
7453                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7454         }
7455
7456         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7457         VectorClear(t->dlightcolor);
7458         t->currentnumlayers = 0;
7459         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7460         {
7461                 int blendfunc1, blendfunc2;
7462                 qboolean depthmask;
7463                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7464                 {
7465                         blendfunc1 = GL_SRC_ALPHA;
7466                         blendfunc2 = GL_ONE;
7467                 }
7468                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7469                 {
7470                         blendfunc1 = GL_SRC_ALPHA;
7471                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7472                 }
7473                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7474                 {
7475                         blendfunc1 = t->customblendfunc[0];
7476                         blendfunc2 = t->customblendfunc[1];
7477                 }
7478                 else
7479                 {
7480                         blendfunc1 = GL_ONE;
7481                         blendfunc2 = GL_ZERO;
7482                 }
7483                 // don't colormod evilblend textures
7484                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7485                         VectorSet(t->lightmapcolor, 1, 1, 1);
7486                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7487                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7488                 {
7489                         // fullbright is not affected by r_refdef.lightmapintensity
7490                         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]);
7491                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7492                                 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]);
7493                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7494                                 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]);
7495                 }
7496                 else
7497                 {
7498                         vec3_t ambientcolor;
7499                         float colorscale;
7500                         // set the color tint used for lights affecting this surface
7501                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7502                         colorscale = 2;
7503                         // q3bsp has no lightmap updates, so the lightstylevalue that
7504                         // would normally be baked into the lightmap must be
7505                         // applied to the color
7506                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7507                         if (model->type == mod_brushq3)
7508                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7509                         colorscale *= r_refdef.lightmapintensity;
7510                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7511                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7512                         // basic lit geometry
7513                         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]);
7514                         // add pants/shirt if needed
7515                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7516                                 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]);
7517                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7518                                 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]);
7519                         // now add ambient passes if needed
7520                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7521                         {
7522                                 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]);
7523                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7524                                         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]);
7525                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7526                                         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]);
7527                         }
7528                 }
7529                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7530                         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]);
7531                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7532                 {
7533                         // if this is opaque use alpha blend which will darken the earlier
7534                         // passes cheaply.
7535                         //
7536                         // if this is an alpha blended material, all the earlier passes
7537                         // were darkened by fog already, so we only need to add the fog
7538                         // color ontop through the fog mask texture
7539                         //
7540                         // if this is an additive blended material, all the earlier passes
7541                         // were darkened by fog already, and we should not add fog color
7542                         // (because the background was not darkened, there is no fog color
7543                         // that was lost behind it).
7544                         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]);
7545                 }
7546         }
7547
7548         return t->currentframe;
7549 }
7550
7551 rsurfacestate_t rsurface;
7552
7553 void RSurf_ActiveWorldEntity(void)
7554 {
7555         dp_model_t *model = r_refdef.scene.worldmodel;
7556         //if (rsurface.entity == r_refdef.scene.worldentity)
7557         //      return;
7558         rsurface.entity = r_refdef.scene.worldentity;
7559         rsurface.skeleton = NULL;
7560         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7561         rsurface.ent_skinnum = 0;
7562         rsurface.ent_qwskin = -1;
7563         rsurface.ent_shadertime = 0;
7564         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7565         rsurface.matrix = identitymatrix;
7566         rsurface.inversematrix = identitymatrix;
7567         rsurface.matrixscale = 1;
7568         rsurface.inversematrixscale = 1;
7569         R_EntityMatrix(&identitymatrix);
7570         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7571         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7572         rsurface.fograngerecip = r_refdef.fograngerecip;
7573         rsurface.fogheightfade = r_refdef.fogheightfade;
7574         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7575         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7576         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7577         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7578         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7579         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7580         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7581         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7582         rsurface.colormod[3] = 1;
7583         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);
7584         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7585         rsurface.frameblend[0].lerp = 1;
7586         rsurface.ent_alttextures = false;
7587         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7588         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7589         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7590         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7591         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7592         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7593         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7594         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7595         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7596         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7597         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7598         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7599         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7600         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7601         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7602         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7603         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7604         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7605         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7606         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7607         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7608         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7609         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7610         rsurface.modelelement3i = model->surfmesh.data_element3i;
7611         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7612         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7613         rsurface.modelelement3s = model->surfmesh.data_element3s;
7614         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7615         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7616         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7617         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7618         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7619         rsurface.modelsurfaces = model->data_surfaces;
7620         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7621         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7622         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7623         rsurface.modelgeneratedvertex = false;
7624         rsurface.batchgeneratedvertex = false;
7625         rsurface.batchfirstvertex = 0;
7626         rsurface.batchnumvertices = 0;
7627         rsurface.batchfirsttriangle = 0;
7628         rsurface.batchnumtriangles = 0;
7629         rsurface.batchvertex3f  = NULL;
7630         rsurface.batchvertex3f_vertexbuffer = NULL;
7631         rsurface.batchvertex3f_bufferoffset = 0;
7632         rsurface.batchsvector3f = NULL;
7633         rsurface.batchsvector3f_vertexbuffer = NULL;
7634         rsurface.batchsvector3f_bufferoffset = 0;
7635         rsurface.batchtvector3f = NULL;
7636         rsurface.batchtvector3f_vertexbuffer = NULL;
7637         rsurface.batchtvector3f_bufferoffset = 0;
7638         rsurface.batchnormal3f  = NULL;
7639         rsurface.batchnormal3f_vertexbuffer = NULL;
7640         rsurface.batchnormal3f_bufferoffset = 0;
7641         rsurface.batchlightmapcolor4f = NULL;
7642         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7643         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7644         rsurface.batchtexcoordtexture2f = NULL;
7645         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7646         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7647         rsurface.batchtexcoordlightmap2f = NULL;
7648         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7649         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7650         rsurface.batchvertexmesh = NULL;
7651         rsurface.batchvertexmeshbuffer = NULL;
7652         rsurface.batchvertex3fbuffer = NULL;
7653         rsurface.batchelement3i = NULL;
7654         rsurface.batchelement3i_indexbuffer = NULL;
7655         rsurface.batchelement3i_bufferoffset = 0;
7656         rsurface.batchelement3s = NULL;
7657         rsurface.batchelement3s_indexbuffer = NULL;
7658         rsurface.batchelement3s_bufferoffset = 0;
7659         rsurface.passcolor4f = NULL;
7660         rsurface.passcolor4f_vertexbuffer = NULL;
7661         rsurface.passcolor4f_bufferoffset = 0;
7662 }
7663
7664 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7665 {
7666         dp_model_t *model = ent->model;
7667         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7668         //      return;
7669         rsurface.entity = (entity_render_t *)ent;
7670         rsurface.skeleton = ent->skeleton;
7671         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7672         rsurface.ent_skinnum = ent->skinnum;
7673         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;
7674         rsurface.ent_shadertime = ent->shadertime;
7675         rsurface.ent_flags = ent->flags;
7676         rsurface.matrix = ent->matrix;
7677         rsurface.inversematrix = ent->inversematrix;
7678         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7679         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7680         R_EntityMatrix(&rsurface.matrix);
7681         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7682         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7683         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7684         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7685         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7686         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7687         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7688         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7689         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7690         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7691         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7692         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7693         rsurface.colormod[3] = ent->alpha;
7694         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7695         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7696         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7697         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7698         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7699         if (ent->model->brush.submodel && !prepass)
7700         {
7701                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7702                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7703         }
7704         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7705         {
7706                 if (ent->animcache_vertex3f)
7707                 {
7708                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7709                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7710                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7711                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7712                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7713                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7714                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7715                 }
7716                 else if (wanttangents)
7717                 {
7718                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7719                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7720                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7721                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7722                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7723                         rsurface.modelvertexmesh = NULL;
7724                         rsurface.modelvertexmeshbuffer = NULL;
7725                         rsurface.modelvertex3fbuffer = NULL;
7726                 }
7727                 else if (wantnormals)
7728                 {
7729                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7730                         rsurface.modelsvector3f = NULL;
7731                         rsurface.modeltvector3f = NULL;
7732                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7733                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7734                         rsurface.modelvertexmesh = NULL;
7735                         rsurface.modelvertexmeshbuffer = NULL;
7736                         rsurface.modelvertex3fbuffer = NULL;
7737                 }
7738                 else
7739                 {
7740                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7741                         rsurface.modelsvector3f = NULL;
7742                         rsurface.modeltvector3f = NULL;
7743                         rsurface.modelnormal3f = NULL;
7744                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7745                         rsurface.modelvertexmesh = NULL;
7746                         rsurface.modelvertexmeshbuffer = NULL;
7747                         rsurface.modelvertex3fbuffer = NULL;
7748                 }
7749                 rsurface.modelvertex3f_vertexbuffer = 0;
7750                 rsurface.modelvertex3f_bufferoffset = 0;
7751                 rsurface.modelsvector3f_vertexbuffer = 0;
7752                 rsurface.modelsvector3f_bufferoffset = 0;
7753                 rsurface.modeltvector3f_vertexbuffer = 0;
7754                 rsurface.modeltvector3f_bufferoffset = 0;
7755                 rsurface.modelnormal3f_vertexbuffer = 0;
7756                 rsurface.modelnormal3f_bufferoffset = 0;
7757                 rsurface.modelgeneratedvertex = true;
7758         }
7759         else
7760         {
7761                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7762                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7763                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7764                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7765                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7766                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7767                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7768                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7769                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7770                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7771                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7772                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7773                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7774                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7775                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7776                 rsurface.modelgeneratedvertex = false;
7777         }
7778         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7779         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7780         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7781         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7782         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7784         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7785         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7787         rsurface.modelelement3i = model->surfmesh.data_element3i;
7788         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7789         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7790         rsurface.modelelement3s = model->surfmesh.data_element3s;
7791         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7792         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7793         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7794         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7795         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7796         rsurface.modelsurfaces = model->data_surfaces;
7797         rsurface.batchgeneratedvertex = false;
7798         rsurface.batchfirstvertex = 0;
7799         rsurface.batchnumvertices = 0;
7800         rsurface.batchfirsttriangle = 0;
7801         rsurface.batchnumtriangles = 0;
7802         rsurface.batchvertex3f  = NULL;
7803         rsurface.batchvertex3f_vertexbuffer = NULL;
7804         rsurface.batchvertex3f_bufferoffset = 0;
7805         rsurface.batchsvector3f = NULL;
7806         rsurface.batchsvector3f_vertexbuffer = NULL;
7807         rsurface.batchsvector3f_bufferoffset = 0;
7808         rsurface.batchtvector3f = NULL;
7809         rsurface.batchtvector3f_vertexbuffer = NULL;
7810         rsurface.batchtvector3f_bufferoffset = 0;
7811         rsurface.batchnormal3f  = NULL;
7812         rsurface.batchnormal3f_vertexbuffer = NULL;
7813         rsurface.batchnormal3f_bufferoffset = 0;
7814         rsurface.batchlightmapcolor4f = NULL;
7815         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7816         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7817         rsurface.batchtexcoordtexture2f = NULL;
7818         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7819         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7820         rsurface.batchtexcoordlightmap2f = NULL;
7821         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7822         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7823         rsurface.batchvertexmesh = NULL;
7824         rsurface.batchvertexmeshbuffer = NULL;
7825         rsurface.batchvertex3fbuffer = NULL;
7826         rsurface.batchelement3i = NULL;
7827         rsurface.batchelement3i_indexbuffer = NULL;
7828         rsurface.batchelement3i_bufferoffset = 0;
7829         rsurface.batchelement3s = NULL;
7830         rsurface.batchelement3s_indexbuffer = NULL;
7831         rsurface.batchelement3s_bufferoffset = 0;
7832         rsurface.passcolor4f = NULL;
7833         rsurface.passcolor4f_vertexbuffer = NULL;
7834         rsurface.passcolor4f_bufferoffset = 0;
7835 }
7836
7837 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)
7838 {
7839         rsurface.entity = r_refdef.scene.worldentity;
7840         rsurface.skeleton = NULL;
7841         rsurface.ent_skinnum = 0;
7842         rsurface.ent_qwskin = -1;
7843         rsurface.ent_shadertime = shadertime;
7844         rsurface.ent_flags = entflags;
7845         rsurface.modelnumvertices = numvertices;
7846         rsurface.modelnumtriangles = numtriangles;
7847         rsurface.matrix = *matrix;
7848         rsurface.inversematrix = *inversematrix;
7849         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7850         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7851         R_EntityMatrix(&rsurface.matrix);
7852         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7853         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7854         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7855         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7856         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7857         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7858         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7859         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7860         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7861         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7862         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7863         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7864         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);
7865         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7866         rsurface.frameblend[0].lerp = 1;
7867         rsurface.ent_alttextures = false;
7868         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7869         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7870         if (wanttangents)
7871         {
7872                 rsurface.modelvertex3f = (float *)vertex3f;
7873                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7874                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7875                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7876         }
7877         else if (wantnormals)
7878         {
7879                 rsurface.modelvertex3f = (float *)vertex3f;
7880                 rsurface.modelsvector3f = NULL;
7881                 rsurface.modeltvector3f = NULL;
7882                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7883         }
7884         else
7885         {
7886                 rsurface.modelvertex3f = (float *)vertex3f;
7887                 rsurface.modelsvector3f = NULL;
7888                 rsurface.modeltvector3f = NULL;
7889                 rsurface.modelnormal3f = NULL;
7890         }
7891         rsurface.modelvertexmesh = NULL;
7892         rsurface.modelvertexmeshbuffer = NULL;
7893         rsurface.modelvertex3fbuffer = NULL;
7894         rsurface.modelvertex3f_vertexbuffer = 0;
7895         rsurface.modelvertex3f_bufferoffset = 0;
7896         rsurface.modelsvector3f_vertexbuffer = 0;
7897         rsurface.modelsvector3f_bufferoffset = 0;
7898         rsurface.modeltvector3f_vertexbuffer = 0;
7899         rsurface.modeltvector3f_bufferoffset = 0;
7900         rsurface.modelnormal3f_vertexbuffer = 0;
7901         rsurface.modelnormal3f_bufferoffset = 0;
7902         rsurface.modelgeneratedvertex = true;
7903         rsurface.modellightmapcolor4f  = (float *)color4f;
7904         rsurface.modellightmapcolor4f_vertexbuffer = 0;
7905         rsurface.modellightmapcolor4f_bufferoffset = 0;
7906         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
7907         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7908         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7909         rsurface.modeltexcoordlightmap2f  = NULL;
7910         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7911         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7912         rsurface.modelelement3i = (int *)element3i;
7913         rsurface.modelelement3i_indexbuffer = NULL;
7914         rsurface.modelelement3i_bufferoffset = 0;
7915         rsurface.modelelement3s = (unsigned short *)element3s;
7916         rsurface.modelelement3s_indexbuffer = NULL;
7917         rsurface.modelelement3s_bufferoffset = 0;
7918         rsurface.modellightmapoffsets = NULL;
7919         rsurface.modelsurfaces = NULL;
7920         rsurface.batchgeneratedvertex = false;
7921         rsurface.batchfirstvertex = 0;
7922         rsurface.batchnumvertices = 0;
7923         rsurface.batchfirsttriangle = 0;
7924         rsurface.batchnumtriangles = 0;
7925         rsurface.batchvertex3f  = NULL;
7926         rsurface.batchvertex3f_vertexbuffer = NULL;
7927         rsurface.batchvertex3f_bufferoffset = 0;
7928         rsurface.batchsvector3f = NULL;
7929         rsurface.batchsvector3f_vertexbuffer = NULL;
7930         rsurface.batchsvector3f_bufferoffset = 0;
7931         rsurface.batchtvector3f = NULL;
7932         rsurface.batchtvector3f_vertexbuffer = NULL;
7933         rsurface.batchtvector3f_bufferoffset = 0;
7934         rsurface.batchnormal3f  = NULL;
7935         rsurface.batchnormal3f_vertexbuffer = NULL;
7936         rsurface.batchnormal3f_bufferoffset = 0;
7937         rsurface.batchlightmapcolor4f = NULL;
7938         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7939         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7940         rsurface.batchtexcoordtexture2f = NULL;
7941         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7942         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7943         rsurface.batchtexcoordlightmap2f = NULL;
7944         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7945         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7946         rsurface.batchvertexmesh = NULL;
7947         rsurface.batchvertexmeshbuffer = NULL;
7948         rsurface.batchvertex3fbuffer = NULL;
7949         rsurface.batchelement3i = NULL;
7950         rsurface.batchelement3i_indexbuffer = NULL;
7951         rsurface.batchelement3i_bufferoffset = 0;
7952         rsurface.batchelement3s = NULL;
7953         rsurface.batchelement3s_indexbuffer = NULL;
7954         rsurface.batchelement3s_bufferoffset = 0;
7955         rsurface.passcolor4f = NULL;
7956         rsurface.passcolor4f_vertexbuffer = NULL;
7957         rsurface.passcolor4f_bufferoffset = 0;
7958
7959         if (rsurface.modelnumvertices && rsurface.modelelement3i)
7960         {
7961                 if ((wantnormals || wanttangents) && !normal3f)
7962                 {
7963                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7964                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7965                 }
7966                 if (wanttangents && !svector3f)
7967                 {
7968                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7969                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7970                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7971                 }
7972         }
7973 }
7974
7975 float RSurf_FogPoint(const float *v)
7976 {
7977         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7978         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7979         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
7980         float FogHeightFade = r_refdef.fogheightfade;
7981         float fogfrac;
7982         unsigned int fogmasktableindex;
7983         if (r_refdef.fogplaneviewabove)
7984                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
7985         else
7986                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
7987         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
7988         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
7989 }
7990
7991 float RSurf_FogVertex(const float *v)
7992 {
7993         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7994         float FogPlaneViewDist = rsurface.fogplaneviewdist;
7995         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
7996         float FogHeightFade = rsurface.fogheightfade;
7997         float fogfrac;
7998         unsigned int fogmasktableindex;
7999         if (r_refdef.fogplaneviewabove)
8000                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8001         else
8002                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8003         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8004         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8005 }
8006
8007 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8008 {
8009         int i;
8010         for (i = 0;i < numelements;i++)
8011                 outelement3i[i] = inelement3i[i] + adjust;
8012 }
8013
8014 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8015 extern cvar_t gl_vbo;
8016 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8017 {
8018         int deformindex;
8019         int firsttriangle;
8020         int numtriangles;
8021         int firstvertex;
8022         int endvertex;
8023         int numvertices;
8024         int surfacefirsttriangle;
8025         int surfacenumtriangles;
8026         int surfacefirstvertex;
8027         int surfaceendvertex;
8028         int surfacenumvertices;
8029         int batchnumvertices;
8030         int batchnumtriangles;
8031         int needsupdate;
8032         int i, j;
8033         qboolean gaps;
8034         qboolean dynamicvertex;
8035         float amplitude;
8036         float animpos;
8037         float scale;
8038         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8039         float waveparms[4];
8040         q3shaderinfo_deform_t *deform;
8041         const msurface_t *surface, *firstsurface;
8042         r_vertexmesh_t *vertexmesh;
8043         if (!texturenumsurfaces)
8044                 return;
8045         // find vertex range of this surface batch
8046         gaps = false;
8047         firstsurface = texturesurfacelist[0];
8048         firsttriangle = firstsurface->num_firsttriangle;
8049         batchnumvertices = 0;
8050         batchnumtriangles = 0;
8051         firstvertex = endvertex = firstsurface->num_firstvertex;
8052         for (i = 0;i < texturenumsurfaces;i++)
8053         {
8054                 surface = texturesurfacelist[i];
8055                 if (surface != firstsurface + i)
8056                         gaps = true;
8057                 surfacefirstvertex = surface->num_firstvertex;
8058                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8059                 surfacenumvertices = surface->num_vertices;
8060                 surfacenumtriangles = surface->num_triangles;
8061                 if (firstvertex > surfacefirstvertex)
8062                         firstvertex = surfacefirstvertex;
8063                 if (endvertex < surfaceendvertex)
8064                         endvertex = surfaceendvertex;
8065                 batchnumvertices += surfacenumvertices;
8066                 batchnumtriangles += surfacenumtriangles;
8067         }
8068
8069         // we now know the vertex range used, and if there are any gaps in it
8070         rsurface.batchfirstvertex = firstvertex;
8071         rsurface.batchnumvertices = endvertex - firstvertex;
8072         rsurface.batchfirsttriangle = firsttriangle;
8073         rsurface.batchnumtriangles = batchnumtriangles;
8074
8075         // this variable holds flags for which properties have been updated that
8076         // may require regenerating vertexmesh array...
8077         needsupdate = 0;
8078
8079         // check if any dynamic vertex processing must occur
8080         dynamicvertex = false;
8081
8082         // if there is a chance of animated vertex colors, it's a dynamic batch
8083         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8084         {
8085                 dynamicvertex = true;
8086                 batchneed |= BATCHNEED_NOGAPS;
8087                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8088         }
8089
8090         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8091         {
8092                 switch (deform->deform)
8093                 {
8094                 default:
8095                 case Q3DEFORM_PROJECTIONSHADOW:
8096                 case Q3DEFORM_TEXT0:
8097                 case Q3DEFORM_TEXT1:
8098                 case Q3DEFORM_TEXT2:
8099                 case Q3DEFORM_TEXT3:
8100                 case Q3DEFORM_TEXT4:
8101                 case Q3DEFORM_TEXT5:
8102                 case Q3DEFORM_TEXT6:
8103                 case Q3DEFORM_TEXT7:
8104                 case Q3DEFORM_NONE:
8105                         break;
8106                 case Q3DEFORM_AUTOSPRITE:
8107                         dynamicvertex = true;
8108                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8109                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8110                         break;
8111                 case Q3DEFORM_AUTOSPRITE2:
8112                         dynamicvertex = true;
8113                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8114                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8115                         break;
8116                 case Q3DEFORM_NORMAL:
8117                         dynamicvertex = true;
8118                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8119                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8120                         break;
8121                 case Q3DEFORM_WAVE:
8122                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8123                                 break; // if wavefunc is a nop, ignore this transform
8124                         dynamicvertex = true;
8125                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8126                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8127                         break;
8128                 case Q3DEFORM_BULGE:
8129                         dynamicvertex = true;
8130                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8131                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8132                         break;
8133                 case Q3DEFORM_MOVE:
8134                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8135                                 break; // if wavefunc is a nop, ignore this transform
8136                         dynamicvertex = true;
8137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8138                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8139                         break;
8140                 }
8141         }
8142         switch(rsurface.texture->tcgen.tcgen)
8143         {
8144         default:
8145         case Q3TCGEN_TEXTURE:
8146                 break;
8147         case Q3TCGEN_LIGHTMAP:
8148                 dynamicvertex = true;
8149                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8150                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8151                 break;
8152         case Q3TCGEN_VECTOR:
8153                 dynamicvertex = true;
8154                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8155                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8156                 break;
8157         case Q3TCGEN_ENVIRONMENT:
8158                 dynamicvertex = true;
8159                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8160                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8161                 break;
8162         }
8163         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8164         {
8165                 dynamicvertex = true;
8166                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8167                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8168         }
8169
8170         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8171         {
8172                 dynamicvertex = true;
8173                 batchneed |= BATCHNEED_NOGAPS;
8174                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8175         }
8176
8177         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8178         {
8179                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8180                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8181                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8182                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8183                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8184                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8185                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8186         }
8187
8188         // when the model data has no vertex buffer (dynamic mesh), we need to
8189         // eliminate gaps
8190         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8191                 batchneed |= BATCHNEED_NOGAPS;
8192
8193         // if needsupdate, we have to do a dynamic vertex batch for sure
8194         if (needsupdate & batchneed)
8195                 dynamicvertex = true;
8196
8197         // see if we need to build vertexmesh from arrays
8198         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8199                 dynamicvertex = true;
8200
8201         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8202         // also some drivers strongly dislike firstvertex
8203         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8204                 dynamicvertex = true;
8205
8206         rsurface.batchvertex3f = rsurface.modelvertex3f;
8207         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8208         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8209         rsurface.batchsvector3f = rsurface.modelsvector3f;
8210         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8211         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8212         rsurface.batchtvector3f = rsurface.modeltvector3f;
8213         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8214         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8215         rsurface.batchnormal3f = rsurface.modelnormal3f;
8216         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8217         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8218         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8219         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8220         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8221         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8222         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8223         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8224         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8225         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8226         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8227         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8228         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8229         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8230         rsurface.batchelement3i = rsurface.modelelement3i;
8231         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8232         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8233         rsurface.batchelement3s = rsurface.modelelement3s;
8234         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8235         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8236
8237         // if any dynamic vertex processing has to occur in software, we copy the
8238         // entire surface list together before processing to rebase the vertices
8239         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8240         //
8241         // if any gaps exist and we do not have a static vertex buffer, we have to
8242         // copy the surface list together to avoid wasting upload bandwidth on the
8243         // vertices in the gaps.
8244         //
8245         // if gaps exist and we have a static vertex buffer, we still have to
8246         // combine the index buffer ranges into one dynamic index buffer.
8247         //
8248         // in all cases we end up with data that can be drawn in one call.
8249
8250         if (!dynamicvertex)
8251         {
8252                 // static vertex data, just set pointers...
8253                 rsurface.batchgeneratedvertex = false;
8254                 // if there are gaps, we want to build a combined index buffer,
8255                 // otherwise use the original static buffer with an appropriate offset
8256                 if (gaps)
8257                 {
8258                         // build a new triangle elements array for this batch
8259                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8260                         rsurface.batchfirsttriangle = 0;
8261                         numtriangles = 0;
8262                         for (i = 0;i < texturenumsurfaces;i++)
8263                         {
8264                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8265                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8266                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8267                                 numtriangles += surfacenumtriangles;
8268                         }
8269                         rsurface.batchelement3i_indexbuffer = NULL;
8270                         rsurface.batchelement3i_bufferoffset = 0;
8271                         rsurface.batchelement3s = NULL;
8272                         rsurface.batchelement3s_indexbuffer = NULL;
8273                         rsurface.batchelement3s_bufferoffset = 0;
8274                         if (endvertex <= 65536)
8275                         {
8276                                 // make a 16bit (unsigned short) index array if possible
8277                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8278                                 for (i = 0;i < numtriangles*3;i++)
8279                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8280                         }
8281                 }
8282                 return;
8283         }
8284
8285         // something needs software processing, do it for real...
8286         // we only directly handle separate array data in this case and then
8287         // generate interleaved data if needed...
8288         rsurface.batchgeneratedvertex = true;
8289
8290         // now copy the vertex data into a combined array and make an index array
8291         // (this is what Quake3 does all the time)
8292         //if (gaps || rsurface.batchfirstvertex)
8293         {
8294                 rsurface.batchvertex3fbuffer = NULL;
8295                 rsurface.batchvertexmesh = NULL;
8296                 rsurface.batchvertexmeshbuffer = NULL;
8297                 rsurface.batchvertex3f = NULL;
8298                 rsurface.batchvertex3f_vertexbuffer = NULL;
8299                 rsurface.batchvertex3f_bufferoffset = 0;
8300                 rsurface.batchsvector3f = NULL;
8301                 rsurface.batchsvector3f_vertexbuffer = NULL;
8302                 rsurface.batchsvector3f_bufferoffset = 0;
8303                 rsurface.batchtvector3f = NULL;
8304                 rsurface.batchtvector3f_vertexbuffer = NULL;
8305                 rsurface.batchtvector3f_bufferoffset = 0;
8306                 rsurface.batchnormal3f = NULL;
8307                 rsurface.batchnormal3f_vertexbuffer = NULL;
8308                 rsurface.batchnormal3f_bufferoffset = 0;
8309                 rsurface.batchlightmapcolor4f = NULL;
8310                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8311                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8312                 rsurface.batchtexcoordtexture2f = NULL;
8313                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8314                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8315                 rsurface.batchtexcoordlightmap2f = NULL;
8316                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8317                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8318                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8319                 rsurface.batchelement3i_indexbuffer = NULL;
8320                 rsurface.batchelement3i_bufferoffset = 0;
8321                 rsurface.batchelement3s = NULL;
8322                 rsurface.batchelement3s_indexbuffer = NULL;
8323                 rsurface.batchelement3s_bufferoffset = 0;
8324                 // we'll only be setting up certain arrays as needed
8325                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8326                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8327                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8328                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8329                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8330                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8331                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8332                 {
8333                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8334                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8335                 }
8336                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8337                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8338                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8339                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8340                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8341                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8342                 numvertices = 0;
8343                 numtriangles = 0;
8344                 for (i = 0;i < texturenumsurfaces;i++)
8345                 {
8346                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8347                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8348                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8349                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8350                         // copy only the data requested
8351                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8352                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8353                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8354                         {
8355                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8356                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8357                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8358                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8359                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8360                                 {
8361                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8362                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8363                                 }
8364                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8365                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8366                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8367                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8368                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8369                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8370                         }
8371                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8372                         numvertices += surfacenumvertices;
8373                         numtriangles += surfacenumtriangles;
8374                 }
8375
8376                 // generate a 16bit index array as well if possible
8377                 // (in general, dynamic batches fit)
8378                 if (numvertices <= 65536)
8379                 {
8380                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8381                         for (i = 0;i < numtriangles*3;i++)
8382                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8383                 }
8384
8385                 // since we've copied everything, the batch now starts at 0
8386                 rsurface.batchfirstvertex = 0;
8387                 rsurface.batchnumvertices = batchnumvertices;
8388                 rsurface.batchfirsttriangle = 0;
8389                 rsurface.batchnumtriangles = batchnumtriangles;
8390         }
8391
8392         // q1bsp surfaces rendered in vertex color mode have to have colors
8393         // calculated based on lightstyles
8394         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8395         {
8396                 // generate color arrays for the surfaces in this list
8397                 int c[4];
8398                 int scale;
8399                 int size3;
8400                 const int *offsets;
8401                 const unsigned char *lm;
8402                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8403                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8404                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8405                 numvertices = 0;
8406                 for (i = 0;i < texturenumsurfaces;i++)
8407                 {
8408                         surface = texturesurfacelist[i];
8409                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8410                         surfacenumvertices = surface->num_vertices;
8411                         if (surface->lightmapinfo->samples)
8412                         {
8413                                 for (j = 0;j < surfacenumvertices;j++)
8414                                 {
8415                                         lm = surface->lightmapinfo->samples + offsets[j];
8416                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8417                                         VectorScale(lm, scale, c);
8418                                         if (surface->lightmapinfo->styles[1] != 255)
8419                                         {
8420                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8421                                                 lm += size3;
8422                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8423                                                 VectorMA(c, scale, lm, c);
8424                                                 if (surface->lightmapinfo->styles[2] != 255)
8425                                                 {
8426                                                         lm += size3;
8427                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8428                                                         VectorMA(c, scale, lm, c);
8429                                                         if (surface->lightmapinfo->styles[3] != 255)
8430                                                         {
8431                                                                 lm += size3;
8432                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8433                                                                 VectorMA(c, scale, lm, c);
8434                                                         }
8435                                                 }
8436                                         }
8437                                         c[0] >>= 7;
8438                                         c[1] >>= 7;
8439                                         c[2] >>= 7;
8440                                         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);
8441                                         numvertices++;
8442                                 }
8443                         }
8444                         else
8445                         {
8446                                 for (j = 0;j < surfacenumvertices;j++)
8447                                 {
8448                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8449                                         numvertices++;
8450                                 }
8451                         }
8452                 }
8453         }
8454
8455         // if vertices are deformed (sprite flares and things in maps, possibly
8456         // water waves, bulges and other deformations), modify the copied vertices
8457         // in place
8458         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8459         {
8460                 switch (deform->deform)
8461                 {
8462                 default:
8463                 case Q3DEFORM_PROJECTIONSHADOW:
8464                 case Q3DEFORM_TEXT0:
8465                 case Q3DEFORM_TEXT1:
8466                 case Q3DEFORM_TEXT2:
8467                 case Q3DEFORM_TEXT3:
8468                 case Q3DEFORM_TEXT4:
8469                 case Q3DEFORM_TEXT5:
8470                 case Q3DEFORM_TEXT6:
8471                 case Q3DEFORM_TEXT7:
8472                 case Q3DEFORM_NONE:
8473                         break;
8474                 case Q3DEFORM_AUTOSPRITE:
8475                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8476                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8477                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8478                         VectorNormalize(newforward);
8479                         VectorNormalize(newright);
8480                         VectorNormalize(newup);
8481 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8482 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8483 //                      rsurface.batchvertex3f_bufferoffset = 0;
8484 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8485 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8486 //                      rsurface.batchsvector3f_bufferoffset = 0;
8487 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8488 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8489 //                      rsurface.batchtvector3f_bufferoffset = 0;
8490 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8491 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8492 //                      rsurface.batchnormal3f_bufferoffset = 0;
8493                         // a single autosprite surface can contain multiple sprites...
8494                         for (j = 0;j < batchnumvertices - 3;j += 4)
8495                         {
8496                                 VectorClear(center);
8497                                 for (i = 0;i < 4;i++)
8498                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8499                                 VectorScale(center, 0.25f, center);
8500                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8501                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8502                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8503                                 for (i = 0;i < 4;i++)
8504                                 {
8505                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8506                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8507                                 }
8508                         }
8509                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8510                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8511                         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);
8512                         break;
8513                 case Q3DEFORM_AUTOSPRITE2:
8514                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8515                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8516                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8517                         VectorNormalize(newforward);
8518                         VectorNormalize(newright);
8519                         VectorNormalize(newup);
8520 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8521 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8522 //                      rsurface.batchvertex3f_bufferoffset = 0;
8523                         {
8524                                 const float *v1, *v2;
8525                                 vec3_t start, end;
8526                                 float f, l;
8527                                 struct
8528                                 {
8529                                         float length2;
8530                                         const float *v1;
8531                                         const float *v2;
8532                                 }
8533                                 shortest[2];
8534                                 memset(shortest, 0, sizeof(shortest));
8535                                 // a single autosprite surface can contain multiple sprites...
8536                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8537                                 {
8538                                         VectorClear(center);
8539                                         for (i = 0;i < 4;i++)
8540                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8541                                         VectorScale(center, 0.25f, center);
8542                                         // find the two shortest edges, then use them to define the
8543                                         // axis vectors for rotating around the central axis
8544                                         for (i = 0;i < 6;i++)
8545                                         {
8546                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8547                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8548                                                 l = VectorDistance2(v1, v2);
8549                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8550                                                 if (v1[2] != v2[2])
8551                                                         l += (1.0f / 1024.0f);
8552                                                 if (shortest[0].length2 > l || i == 0)
8553                                                 {
8554                                                         shortest[1] = shortest[0];
8555                                                         shortest[0].length2 = l;
8556                                                         shortest[0].v1 = v1;
8557                                                         shortest[0].v2 = v2;
8558                                                 }
8559                                                 else if (shortest[1].length2 > l || i == 1)
8560                                                 {
8561                                                         shortest[1].length2 = l;
8562                                                         shortest[1].v1 = v1;
8563                                                         shortest[1].v2 = v2;
8564                                                 }
8565                                         }
8566                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8567                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8568                                         // this calculates the right vector from the shortest edge
8569                                         // and the up vector from the edge midpoints
8570                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8571                                         VectorNormalize(right);
8572                                         VectorSubtract(end, start, up);
8573                                         VectorNormalize(up);
8574                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8575                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8576                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8577                                         VectorNegate(forward, forward);
8578                                         VectorReflect(forward, 0, up, forward);
8579                                         VectorNormalize(forward);
8580                                         CrossProduct(up, forward, newright);
8581                                         VectorNormalize(newright);
8582                                         // rotate the quad around the up axis vector, this is made
8583                                         // especially easy by the fact we know the quad is flat,
8584                                         // so we only have to subtract the center position and
8585                                         // measure distance along the right vector, and then
8586                                         // multiply that by the newright vector and add back the
8587                                         // center position
8588                                         // we also need to subtract the old position to undo the
8589                                         // displacement from the center, which we do with a
8590                                         // DotProduct, the subtraction/addition of center is also
8591                                         // optimized into DotProducts here
8592                                         l = DotProduct(right, center);
8593                                         for (i = 0;i < 4;i++)
8594                                         {
8595                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8596                                                 f = DotProduct(right, v1) - l;
8597                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8598                                         }
8599                                 }
8600                         }
8601                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8602                         {
8603 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8604 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8605 //                              rsurface.batchnormal3f_bufferoffset = 0;
8606                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8607                         }
8608                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8609                         {
8610 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8611 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8612 //                              rsurface.batchsvector3f_bufferoffset = 0;
8613 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8614 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8615 //                              rsurface.batchtvector3f_bufferoffset = 0;
8616                                 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);
8617                         }
8618                         break;
8619                 case Q3DEFORM_NORMAL:
8620                         // deform the normals to make reflections wavey
8621                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8622                         rsurface.batchnormal3f_vertexbuffer = NULL;
8623                         rsurface.batchnormal3f_bufferoffset = 0;
8624                         for (j = 0;j < batchnumvertices;j++)
8625                         {
8626                                 float vertex[3];
8627                                 float *normal = rsurface.batchnormal3f + 3*j;
8628                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8629                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8630                                 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]);
8631                                 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]);
8632                                 VectorNormalize(normal);
8633                         }
8634                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8635                         {
8636 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8637 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8638 //                              rsurface.batchsvector3f_bufferoffset = 0;
8639 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8640 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8641 //                              rsurface.batchtvector3f_bufferoffset = 0;
8642                                 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);
8643                         }
8644                         break;
8645                 case Q3DEFORM_WAVE:
8646                         // deform vertex array to make wavey water and flags and such
8647                         waveparms[0] = deform->waveparms[0];
8648                         waveparms[1] = deform->waveparms[1];
8649                         waveparms[2] = deform->waveparms[2];
8650                         waveparms[3] = deform->waveparms[3];
8651                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8652                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8653                         // this is how a divisor of vertex influence on deformation
8654                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8655                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8656 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8657 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8658 //                      rsurface.batchvertex3f_bufferoffset = 0;
8659 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8660 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8661 //                      rsurface.batchnormal3f_bufferoffset = 0;
8662                         for (j = 0;j < batchnumvertices;j++)
8663                         {
8664                                 // if the wavefunc depends on time, evaluate it per-vertex
8665                                 if (waveparms[3])
8666                                 {
8667                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8668                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8669                                 }
8670                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8671                         }
8672                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8673                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8674                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8675                         {
8676 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8677 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8678 //                              rsurface.batchsvector3f_bufferoffset = 0;
8679 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8680 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8681 //                              rsurface.batchtvector3f_bufferoffset = 0;
8682                                 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);
8683                         }
8684                         break;
8685                 case Q3DEFORM_BULGE:
8686                         // deform vertex array to make the surface have moving bulges
8687 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8688 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8689 //                      rsurface.batchvertex3f_bufferoffset = 0;
8690 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8691 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8692 //                      rsurface.batchnormal3f_bufferoffset = 0;
8693                         for (j = 0;j < batchnumvertices;j++)
8694                         {
8695                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8696                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8697                         }
8698                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8699                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8700                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8701                         {
8702 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8703 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8704 //                              rsurface.batchsvector3f_bufferoffset = 0;
8705 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8706 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8707 //                              rsurface.batchtvector3f_bufferoffset = 0;
8708                                 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);
8709                         }
8710                         break;
8711                 case Q3DEFORM_MOVE:
8712                         // deform vertex array
8713                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8714                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8715                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8716                         VectorScale(deform->parms, scale, waveparms);
8717 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8718 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8719 //                      rsurface.batchvertex3f_bufferoffset = 0;
8720                         for (j = 0;j < batchnumvertices;j++)
8721                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8722                         break;
8723                 }
8724         }
8725
8726         // generate texcoords based on the chosen texcoord source
8727         switch(rsurface.texture->tcgen.tcgen)
8728         {
8729         default:
8730         case Q3TCGEN_TEXTURE:
8731                 break;
8732         case Q3TCGEN_LIGHTMAP:
8733 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8734 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8735 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8736                 if (rsurface.batchtexcoordlightmap2f)
8737                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8738                 break;
8739         case Q3TCGEN_VECTOR:
8740 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8741 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8742 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8743                 for (j = 0;j < batchnumvertices;j++)
8744                 {
8745                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8746                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8747                 }
8748                 break;
8749         case Q3TCGEN_ENVIRONMENT:
8750                 // make environment reflections using a spheremap
8751                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8752                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8753                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8754                 for (j = 0;j < batchnumvertices;j++)
8755                 {
8756                         // identical to Q3A's method, but executed in worldspace so
8757                         // carried models can be shiny too
8758
8759                         float viewer[3], d, reflected[3], worldreflected[3];
8760
8761                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8762                         // VectorNormalize(viewer);
8763
8764                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8765
8766                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8767                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8768                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8769                         // note: this is proportinal to viewer, so we can normalize later
8770
8771                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8772                         VectorNormalize(worldreflected);
8773
8774                         // note: this sphere map only uses world x and z!
8775                         // so positive and negative y will LOOK THE SAME.
8776                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8777                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8778                 }
8779                 break;
8780         }
8781         // the only tcmod that needs software vertex processing is turbulent, so
8782         // check for it here and apply the changes if needed
8783         // and we only support that as the first one
8784         // (handling a mixture of turbulent and other tcmods would be problematic
8785         //  without punting it entirely to a software path)
8786         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8787         {
8788                 amplitude = rsurface.texture->tcmods[0].parms[1];
8789                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8790 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8791 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8792 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8793                 for (j = 0;j < batchnumvertices;j++)
8794                 {
8795                         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);
8796                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8797                 }
8798         }
8799
8800         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8801         {
8802                 // convert the modified arrays to vertex structs
8803 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8804 //              rsurface.batchvertexmeshbuffer = NULL;
8805                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8806                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8807                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8808                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8809                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8810                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8811                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8812                 {
8813                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8814                         {
8815                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8816                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8817                         }
8818                 }
8819                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8820                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8821                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8822                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8823                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8824                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8825                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8826                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8827                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8828         }
8829 }
8830
8831 void RSurf_DrawBatch(void)
8832 {
8833         // sometimes a zero triangle surface (usually a degenerate patch) makes it
8834         // through the pipeline, killing it earlier in the pipeline would have
8835         // per-surface overhead rather than per-batch overhead, so it's best to
8836         // reject it here, before it hits glDraw.
8837         if (rsurface.batchnumtriangles == 0)
8838                 return;
8839 #if 0
8840         // batch debugging code
8841         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8842         {
8843                 int i;
8844                 int j;
8845                 int c;
8846                 const int *e;
8847                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8848                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8849                 {
8850                         c = e[i];
8851                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8852                         {
8853                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8854                                 {
8855                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8856                                                 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);
8857                                         break;
8858                                 }
8859                         }
8860                 }
8861         }
8862 #endif
8863         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);
8864 }
8865
8866 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8867 {
8868         // pick the closest matching water plane
8869         int planeindex, vertexindex, bestplaneindex = -1;
8870         float d, bestd;
8871         vec3_t vert;
8872         const float *v;
8873         r_waterstate_waterplane_t *p;
8874         qboolean prepared = false;
8875         bestd = 0;
8876         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8877         {
8878                 if(p->camera_entity != rsurface.texture->camera_entity)
8879                         continue;
8880                 d = 0;
8881                 if(!prepared)
8882                 {
8883                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8884                         prepared = true;
8885                         if(rsurface.batchnumvertices == 0)
8886                                 break;
8887                 }
8888                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8889                 {
8890                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
8891                         d += fabs(PlaneDiff(vert, &p->plane));
8892                 }
8893                 if (bestd > d || bestplaneindex < 0)
8894                 {
8895                         bestd = d;
8896                         bestplaneindex = planeindex;
8897                 }
8898         }
8899         return bestplaneindex;
8900         // NOTE: this MAY return a totally unrelated water plane; we can ignore
8901         // this situation though, as it might be better to render single larger
8902         // batches with useless stuff (backface culled for example) than to
8903         // render multiple smaller batches
8904 }
8905
8906 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8907 {
8908         int i;
8909         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8910         rsurface.passcolor4f_vertexbuffer = 0;
8911         rsurface.passcolor4f_bufferoffset = 0;
8912         for (i = 0;i < rsurface.batchnumvertices;i++)
8913                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8914 }
8915
8916 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8917 {
8918         int i;
8919         float f;
8920         const float *v;
8921         const float *c;
8922         float *c2;
8923         if (rsurface.passcolor4f)
8924         {
8925                 // generate color arrays
8926                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8927                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8928                 rsurface.passcolor4f_vertexbuffer = 0;
8929                 rsurface.passcolor4f_bufferoffset = 0;
8930                 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)
8931                 {
8932                         f = RSurf_FogVertex(v);
8933                         c2[0] = c[0] * f;
8934                         c2[1] = c[1] * f;
8935                         c2[2] = c[2] * f;
8936                         c2[3] = c[3];
8937                 }
8938         }
8939         else
8940         {
8941                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8942                 rsurface.passcolor4f_vertexbuffer = 0;
8943                 rsurface.passcolor4f_bufferoffset = 0;
8944                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8945                 {
8946                         f = RSurf_FogVertex(v);
8947                         c2[0] = f;
8948                         c2[1] = f;
8949                         c2[2] = f;
8950                         c2[3] = 1;
8951                 }
8952         }
8953 }
8954
8955 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8956 {
8957         int i;
8958         float f;
8959         const float *v;
8960         const float *c;
8961         float *c2;
8962         if (!rsurface.passcolor4f)
8963                 return;
8964         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8965         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8966         rsurface.passcolor4f_vertexbuffer = 0;
8967         rsurface.passcolor4f_bufferoffset = 0;
8968         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)
8969         {
8970                 f = RSurf_FogVertex(v);
8971                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8972                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8973                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8974                 c2[3] = c[3];
8975         }
8976 }
8977
8978 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
8979 {
8980         int i;
8981         const float *c;
8982         float *c2;
8983         if (!rsurface.passcolor4f)
8984                 return;
8985         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8986         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8987         rsurface.passcolor4f_vertexbuffer = 0;
8988         rsurface.passcolor4f_bufferoffset = 0;
8989         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
8990         {
8991                 c2[0] = c[0] * r;
8992                 c2[1] = c[1] * g;
8993                 c2[2] = c[2] * b;
8994                 c2[3] = c[3] * a;
8995         }
8996 }
8997
8998 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
8999 {
9000         int i;
9001         const float *c;
9002         float *c2;
9003         if (!rsurface.passcolor4f)
9004                 return;
9005         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9006         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9007         rsurface.passcolor4f_vertexbuffer = 0;
9008         rsurface.passcolor4f_bufferoffset = 0;
9009         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9010         {
9011                 c2[0] = c[0] + r_refdef.scene.ambient;
9012                 c2[1] = c[1] + r_refdef.scene.ambient;
9013                 c2[2] = c[2] + r_refdef.scene.ambient;
9014                 c2[3] = c[3];
9015         }
9016 }
9017
9018 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9019 {
9020         // TODO: optimize
9021         rsurface.passcolor4f = NULL;
9022         rsurface.passcolor4f_vertexbuffer = 0;
9023         rsurface.passcolor4f_bufferoffset = 0;
9024         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9025         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9026         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9027         GL_Color(r, g, b, a);
9028         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9029         RSurf_DrawBatch();
9030 }
9031
9032 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9033 {
9034         // TODO: optimize applyfog && applycolor case
9035         // just apply fog if necessary, and tint the fog color array if necessary
9036         rsurface.passcolor4f = NULL;
9037         rsurface.passcolor4f_vertexbuffer = 0;
9038         rsurface.passcolor4f_bufferoffset = 0;
9039         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9040         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9041         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9042         GL_Color(r, g, b, a);
9043         RSurf_DrawBatch();
9044 }
9045
9046 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9047 {
9048         // TODO: optimize
9049         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9050         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9051         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9052         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9053         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9054         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9055         GL_Color(r, g, b, a);
9056         RSurf_DrawBatch();
9057 }
9058
9059 static void RSurf_DrawBatch_GL11_ClampColor(void)
9060 {
9061         int i;
9062         const float *c1;
9063         float *c2;
9064         if (!rsurface.passcolor4f)
9065                 return;
9066         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9067         {
9068                 c2[0] = bound(0.0f, c1[0], 1.0f);
9069                 c2[1] = bound(0.0f, c1[1], 1.0f);
9070                 c2[2] = bound(0.0f, c1[2], 1.0f);
9071                 c2[3] = bound(0.0f, c1[3], 1.0f);
9072         }
9073 }
9074
9075 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9076 {
9077         int i;
9078         float f;
9079         const float *v;
9080         const float *n;
9081         float *c;
9082         //vec3_t eyedir;
9083
9084         // fake shading
9085         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9086         rsurface.passcolor4f_vertexbuffer = 0;
9087         rsurface.passcolor4f_bufferoffset = 0;
9088         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)
9089         {
9090                 f = -DotProduct(r_refdef.view.forward, n);
9091                 f = max(0, f);
9092                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9093                 f *= r_refdef.lightmapintensity;
9094                 Vector4Set(c, f, f, f, 1);
9095         }
9096 }
9097
9098 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9099 {
9100         RSurf_DrawBatch_GL11_ApplyFakeLight();
9101         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9102         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9103         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9104         GL_Color(r, g, b, a);
9105         RSurf_DrawBatch();
9106 }
9107
9108 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9109 {
9110         int i;
9111         float f;
9112         float alpha;
9113         const float *v;
9114         const float *n;
9115         float *c;
9116         vec3_t ambientcolor;
9117         vec3_t diffusecolor;
9118         vec3_t lightdir;
9119         // TODO: optimize
9120         // model lighting
9121         VectorCopy(rsurface.modellight_lightdir, lightdir);
9122         f = 0.5f * r_refdef.lightmapintensity;
9123         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9124         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9125         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9126         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9127         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9128         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9129         alpha = *a;
9130         if (VectorLength2(diffusecolor) > 0)
9131         {
9132                 // q3-style directional shading
9133                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9134                 rsurface.passcolor4f_vertexbuffer = 0;
9135                 rsurface.passcolor4f_bufferoffset = 0;
9136                 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)
9137                 {
9138                         if ((f = DotProduct(n, lightdir)) > 0)
9139                                 VectorMA(ambientcolor, f, diffusecolor, c);
9140                         else
9141                                 VectorCopy(ambientcolor, c);
9142                         c[3] = alpha;
9143                 }
9144                 *r = 1;
9145                 *g = 1;
9146                 *b = 1;
9147                 *a = 1;
9148                 *applycolor = false;
9149         }
9150         else
9151         {
9152                 *r = ambientcolor[0];
9153                 *g = ambientcolor[1];
9154                 *b = ambientcolor[2];
9155                 rsurface.passcolor4f = NULL;
9156                 rsurface.passcolor4f_vertexbuffer = 0;
9157                 rsurface.passcolor4f_bufferoffset = 0;
9158         }
9159 }
9160
9161 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9162 {
9163         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9164         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9165         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9166         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9167         GL_Color(r, g, b, a);
9168         RSurf_DrawBatch();
9169 }
9170
9171 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9172 {
9173         int i;
9174         float f;
9175         const float *v;
9176         float *c;
9177         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9178         {
9179                 f = 1 - RSurf_FogVertex(v);
9180                 c[0] = r;
9181                 c[1] = g;
9182                 c[2] = b;
9183                 c[3] = f * a;
9184         }
9185 }
9186
9187 void RSurf_SetupDepthAndCulling(void)
9188 {
9189         // submodels are biased to avoid z-fighting with world surfaces that they
9190         // may be exactly overlapping (avoids z-fighting artifacts on certain
9191         // doors and things in Quake maps)
9192         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9193         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9194         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9195         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9196 }
9197
9198 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9199 {
9200         // transparent sky would be ridiculous
9201         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9202                 return;
9203         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9204         skyrenderlater = true;
9205         RSurf_SetupDepthAndCulling();
9206         GL_DepthMask(true);
9207         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9208         // skymasking on them, and Quake3 never did sky masking (unlike
9209         // software Quake and software Quake2), so disable the sky masking
9210         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9211         // and skymasking also looks very bad when noclipping outside the
9212         // level, so don't use it then either.
9213         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9214         {
9215                 R_Mesh_ResetTextureState();
9216                 if (skyrendermasked)
9217                 {
9218                         R_SetupShader_DepthOrShadow();
9219                         // depth-only (masking)
9220                         GL_ColorMask(0,0,0,0);
9221                         // just to make sure that braindead drivers don't draw
9222                         // anything despite that colormask...
9223                         GL_BlendFunc(GL_ZERO, GL_ONE);
9224                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9225                         if (rsurface.batchvertex3fbuffer)
9226                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9227                         else
9228                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9229                 }
9230                 else
9231                 {
9232                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9233                         // fog sky
9234                         GL_BlendFunc(GL_ONE, GL_ZERO);
9235                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9236                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9237                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9238                 }
9239                 RSurf_DrawBatch();
9240                 if (skyrendermasked)
9241                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9242         }
9243         R_Mesh_ResetTextureState();
9244         GL_Color(1, 1, 1, 1);
9245 }
9246
9247 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9248 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9249 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9250 {
9251         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9252                 return;
9253         if (prepass)
9254         {
9255                 // render screenspace normalmap to texture
9256                 GL_DepthMask(true);
9257                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9258                 RSurf_DrawBatch();
9259                 return;
9260         }
9261
9262         // bind lightmap texture
9263
9264         // water/refraction/reflection/camera surfaces have to be handled specially
9265         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9266         {
9267                 int start, end, startplaneindex;
9268                 for (start = 0;start < texturenumsurfaces;start = end)
9269                 {
9270                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9271                         if(startplaneindex < 0)
9272                         {
9273                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9274                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9275                                 end = start + 1;
9276                                 continue;
9277                         }
9278                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9279                                 ;
9280                         // now that we have a batch using the same planeindex, render it
9281                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9282                         {
9283                                 // render water or distortion background
9284                                 GL_DepthMask(true);
9285                                 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));
9286                                 RSurf_DrawBatch();
9287                                 // blend surface on top
9288                                 GL_DepthMask(false);
9289                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9290                                 RSurf_DrawBatch();
9291                         }
9292                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9293                         {
9294                                 // render surface with reflection texture as input
9295                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9296                                 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));
9297                                 RSurf_DrawBatch();
9298                         }
9299                 }
9300                 return;
9301         }
9302
9303         // render surface batch normally
9304         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9305         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9306         RSurf_DrawBatch();
9307 }
9308
9309 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9310 {
9311         // OpenGL 1.3 path - anything not completely ancient
9312         qboolean applycolor;
9313         qboolean applyfog;
9314         int layerindex;
9315         const texturelayer_t *layer;
9316         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);
9317         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9318
9319         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9320         {
9321                 vec4_t layercolor;
9322                 int layertexrgbscale;
9323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9324                 {
9325                         if (layerindex == 0)
9326                                 GL_AlphaTest(true);
9327                         else
9328                         {
9329                                 GL_AlphaTest(false);
9330                                 GL_DepthFunc(GL_EQUAL);
9331                         }
9332                 }
9333                 GL_DepthMask(layer->depthmask && writedepth);
9334                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9335                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9336                 {
9337                         layertexrgbscale = 4;
9338                         VectorScale(layer->color, 0.25f, layercolor);
9339                 }
9340                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9341                 {
9342                         layertexrgbscale = 2;
9343                         VectorScale(layer->color, 0.5f, layercolor);
9344                 }
9345                 else
9346                 {
9347                         layertexrgbscale = 1;
9348                         VectorScale(layer->color, 1.0f, layercolor);
9349                 }
9350                 layercolor[3] = layer->color[3];
9351                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9352                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9353                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9354                 switch (layer->type)
9355                 {
9356                 case TEXTURELAYERTYPE_LITTEXTURE:
9357                         // single-pass lightmapped texture with 2x rgbscale
9358                         R_Mesh_TexBind(0, r_texture_white);
9359                         R_Mesh_TexMatrix(0, NULL);
9360                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9361                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9362                         R_Mesh_TexBind(1, layer->texture);
9363                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9364                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9365                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9366                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9367                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9368                         else if (FAKELIGHT_ENABLED)
9369                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9370                         else if (rsurface.uselightmaptexture)
9371                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9372                         else
9373                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9374                         break;
9375                 case TEXTURELAYERTYPE_TEXTURE:
9376                         // singletexture unlit texture with transparency support
9377                         R_Mesh_TexBind(0, layer->texture);
9378                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9379                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9380                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9381                         R_Mesh_TexBind(1, 0);
9382                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9383                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9384                         break;
9385                 case TEXTURELAYERTYPE_FOG:
9386                         // singletexture fogging
9387                         if (layer->texture)
9388                         {
9389                                 R_Mesh_TexBind(0, layer->texture);
9390                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9391                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9392                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9393                         }
9394                         else
9395                         {
9396                                 R_Mesh_TexBind(0, 0);
9397                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9398                         }
9399                         R_Mesh_TexBind(1, 0);
9400                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9401                         // generate a color array for the fog pass
9402                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9403                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9404                         RSurf_DrawBatch();
9405                         break;
9406                 default:
9407                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9408                 }
9409         }
9410         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9411         {
9412                 GL_DepthFunc(GL_LEQUAL);
9413                 GL_AlphaTest(false);
9414         }
9415 }
9416
9417 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9418 {
9419         // OpenGL 1.1 - crusty old voodoo path
9420         qboolean applyfog;
9421         int layerindex;
9422         const texturelayer_t *layer;
9423         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);
9424         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9425
9426         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9427         {
9428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9429                 {
9430                         if (layerindex == 0)
9431                                 GL_AlphaTest(true);
9432                         else
9433                         {
9434                                 GL_AlphaTest(false);
9435                                 GL_DepthFunc(GL_EQUAL);
9436                         }
9437                 }
9438                 GL_DepthMask(layer->depthmask && writedepth);
9439                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9440                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9441                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9442                 switch (layer->type)
9443                 {
9444                 case TEXTURELAYERTYPE_LITTEXTURE:
9445                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9446                         {
9447                                 // two-pass lit texture with 2x rgbscale
9448                                 // first the lightmap pass
9449                                 R_Mesh_TexBind(0, r_texture_white);
9450                                 R_Mesh_TexMatrix(0, NULL);
9451                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9452                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9453                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9454                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9455                                 else if (FAKELIGHT_ENABLED)
9456                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9457                                 else if (rsurface.uselightmaptexture)
9458                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9459                                 else
9460                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9461                                 // then apply the texture to it
9462                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9463                                 R_Mesh_TexBind(0, layer->texture);
9464                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9465                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9466                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9467                                 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);
9468                         }
9469                         else
9470                         {
9471                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9472                                 R_Mesh_TexBind(0, layer->texture);
9473                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9474                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9475                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9476                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9477                                         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);
9478                                 else
9479                                         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);
9480                         }
9481                         break;
9482                 case TEXTURELAYERTYPE_TEXTURE:
9483                         // singletexture unlit texture with transparency support
9484                         R_Mesh_TexBind(0, layer->texture);
9485                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9486                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9487                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9488                         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);
9489                         break;
9490                 case TEXTURELAYERTYPE_FOG:
9491                         // singletexture fogging
9492                         if (layer->texture)
9493                         {
9494                                 R_Mesh_TexBind(0, layer->texture);
9495                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9496                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9497                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9498                         }
9499                         else
9500                         {
9501                                 R_Mesh_TexBind(0, 0);
9502                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9503                         }
9504                         // generate a color array for the fog pass
9505                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9506                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9507                         RSurf_DrawBatch();
9508                         break;
9509                 default:
9510                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9511                 }
9512         }
9513         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9514         {
9515                 GL_DepthFunc(GL_LEQUAL);
9516                 GL_AlphaTest(false);
9517         }
9518 }
9519
9520 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9521 {
9522         int vi;
9523         int j;
9524         r_vertexgeneric_t *batchvertex;
9525         float c[4];
9526
9527 //      R_Mesh_ResetTextureState();
9528         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9529
9530         if(rsurface.texture && rsurface.texture->currentskinframe)
9531         {
9532                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9533                 c[3] *= rsurface.texture->currentalpha;
9534         }
9535         else
9536         {
9537                 c[0] = 1;
9538                 c[1] = 0;
9539                 c[2] = 1;
9540                 c[3] = 1;
9541         }
9542
9543         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9544         {
9545                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9546                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9547                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9548         }
9549
9550         // brighten it up (as texture value 127 means "unlit")
9551         c[0] *= 2 * r_refdef.view.colorscale;
9552         c[1] *= 2 * r_refdef.view.colorscale;
9553         c[2] *= 2 * r_refdef.view.colorscale;
9554
9555         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9556                 c[3] *= r_wateralpha.value;
9557
9558         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9559         {
9560                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9561                 GL_DepthMask(false);
9562         }
9563         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9564         {
9565                 GL_BlendFunc(GL_ONE, GL_ONE);
9566                 GL_DepthMask(false);
9567         }
9568         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9569         {
9570                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9571                 GL_DepthMask(false);
9572         }
9573         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9574         {
9575                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9576                 GL_DepthMask(false);
9577         }
9578         else
9579         {
9580                 GL_BlendFunc(GL_ONE, GL_ZERO);
9581                 GL_DepthMask(writedepth);
9582         }
9583
9584         if (r_showsurfaces.integer == 3)
9585         {
9586                 rsurface.passcolor4f = NULL;
9587
9588                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9589                 {
9590                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9591
9592                         rsurface.passcolor4f = NULL;
9593                         rsurface.passcolor4f_vertexbuffer = 0;
9594                         rsurface.passcolor4f_bufferoffset = 0;
9595                 }
9596                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9597                 {
9598                         qboolean applycolor = true;
9599                         float one = 1.0;
9600
9601                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9602
9603                         r_refdef.lightmapintensity = 1;
9604                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9605                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9606                 }
9607                 else if (FAKELIGHT_ENABLED)
9608                 {
9609                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9610
9611                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9612                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9613                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9614                 }
9615                 else
9616                 {
9617                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9618
9619                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9620                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9621                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9622                 }
9623
9624                 if(!rsurface.passcolor4f)
9625                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9626
9627                 RSurf_DrawBatch_GL11_ApplyAmbient();
9628                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9629                 if(r_refdef.fogenabled)
9630                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9631                 RSurf_DrawBatch_GL11_ClampColor();
9632
9633                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9634                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9635                 RSurf_DrawBatch();
9636         }
9637         else if (!r_refdef.view.showdebug)
9638         {
9639                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9640                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9641                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9642                 {
9643                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9644                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9645                 }
9646                 R_Mesh_PrepareVertices_Generic_Unlock();
9647                 RSurf_DrawBatch();
9648         }
9649         else if (r_showsurfaces.integer == 4)
9650         {
9651                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9652                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9653                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9654                 {
9655                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9656                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9657                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9658                 }
9659                 R_Mesh_PrepareVertices_Generic_Unlock();
9660                 RSurf_DrawBatch();
9661         }
9662         else if (r_showsurfaces.integer == 2)
9663         {
9664                 const int *e;
9665                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9666                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9667                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9668                 {
9669                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9670                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9671                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9672                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9673                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9674                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9675                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9676                 }
9677                 R_Mesh_PrepareVertices_Generic_Unlock();
9678                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9679         }
9680         else
9681         {
9682                 int texturesurfaceindex;
9683                 int k;
9684                 const msurface_t *surface;
9685                 float surfacecolor4f[4];
9686                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9687                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9688                 vi = 0;
9689                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9690                 {
9691                         surface = texturesurfacelist[texturesurfaceindex];
9692                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9693                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9694                         for (j = 0;j < surface->num_vertices;j++)
9695                         {
9696                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9697                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9698                                 vi++;
9699                         }
9700                 }
9701                 R_Mesh_PrepareVertices_Generic_Unlock();
9702                 RSurf_DrawBatch();
9703         }
9704 }
9705
9706 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9707 {
9708         CHECKGLERROR
9709         RSurf_SetupDepthAndCulling();
9710         if (r_showsurfaces.integer)
9711         {
9712                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9713                 return;
9714         }
9715         switch (vid.renderpath)
9716         {
9717         case RENDERPATH_GL20:
9718         case RENDERPATH_D3D9:
9719         case RENDERPATH_D3D10:
9720         case RENDERPATH_D3D11:
9721         case RENDERPATH_SOFT:
9722         case RENDERPATH_GLES2:
9723                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9724                 break;
9725         case RENDERPATH_GL13:
9726                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9727                 break;
9728         case RENDERPATH_GL11:
9729                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9730                 break;
9731         }
9732         CHECKGLERROR
9733 }
9734
9735 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9736 {
9737         CHECKGLERROR
9738         RSurf_SetupDepthAndCulling();
9739         if (r_showsurfaces.integer)
9740         {
9741                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9742                 return;
9743         }
9744         switch (vid.renderpath)
9745         {
9746         case RENDERPATH_GL20:
9747         case RENDERPATH_D3D9:
9748         case RENDERPATH_D3D10:
9749         case RENDERPATH_D3D11:
9750         case RENDERPATH_SOFT:
9751         case RENDERPATH_GLES2:
9752                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9753                 break;
9754         case RENDERPATH_GL13:
9755                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9756                 break;
9757         case RENDERPATH_GL11:
9758                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9759                 break;
9760         }
9761         CHECKGLERROR
9762 }
9763
9764 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9765 {
9766         int i, j;
9767         int texturenumsurfaces, endsurface;
9768         texture_t *texture;
9769         const msurface_t *surface;
9770 #define MAXBATCH_TRANSPARENTSURFACES 256
9771         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9772
9773         // if the model is static it doesn't matter what value we give for
9774         // wantnormals and wanttangents, so this logic uses only rules applicable
9775         // to a model, knowing that they are meaningless otherwise
9776         if (ent == r_refdef.scene.worldentity)
9777                 RSurf_ActiveWorldEntity();
9778         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9779                 RSurf_ActiveModelEntity(ent, false, false, false);
9780         else
9781         {
9782                 switch (vid.renderpath)
9783                 {
9784                 case RENDERPATH_GL20:
9785                 case RENDERPATH_D3D9:
9786                 case RENDERPATH_D3D10:
9787                 case RENDERPATH_D3D11:
9788                 case RENDERPATH_SOFT:
9789                 case RENDERPATH_GLES2:
9790                         RSurf_ActiveModelEntity(ent, true, true, false);
9791                         break;
9792                 case RENDERPATH_GL13:
9793                 case RENDERPATH_GL11:
9794                         RSurf_ActiveModelEntity(ent, true, false, false);
9795                         break;
9796                 }
9797         }
9798
9799         if (r_transparentdepthmasking.integer)
9800         {
9801                 qboolean setup = false;
9802                 for (i = 0;i < numsurfaces;i = j)
9803                 {
9804                         j = i + 1;
9805                         surface = rsurface.modelsurfaces + surfacelist[i];
9806                         texture = surface->texture;
9807                         rsurface.texture = R_GetCurrentTexture(texture);
9808                         rsurface.lightmaptexture = NULL;
9809                         rsurface.deluxemaptexture = NULL;
9810                         rsurface.uselightmaptexture = false;
9811                         // scan ahead until we find a different texture
9812                         endsurface = min(i + 1024, numsurfaces);
9813                         texturenumsurfaces = 0;
9814                         texturesurfacelist[texturenumsurfaces++] = surface;
9815                         for (;j < endsurface;j++)
9816                         {
9817                                 surface = rsurface.modelsurfaces + surfacelist[j];
9818                                 if (texture != surface->texture)
9819                                         break;
9820                                 texturesurfacelist[texturenumsurfaces++] = surface;
9821                         }
9822                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9823                                 continue;
9824                         // render the range of surfaces as depth
9825                         if (!setup)
9826                         {
9827                                 setup = true;
9828                                 GL_ColorMask(0,0,0,0);
9829                                 GL_Color(1,1,1,1);
9830                                 GL_DepthTest(true);
9831                                 GL_BlendFunc(GL_ONE, GL_ZERO);
9832                                 GL_DepthMask(true);
9833 //                              R_Mesh_ResetTextureState();
9834                                 R_SetupShader_DepthOrShadow();
9835                         }
9836                         RSurf_SetupDepthAndCulling();
9837                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9838                         if (rsurface.batchvertex3fbuffer)
9839                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9840                         else
9841                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9842                         RSurf_DrawBatch();
9843                 }
9844                 if (setup)
9845                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9846         }
9847
9848         for (i = 0;i < numsurfaces;i = j)
9849         {
9850                 j = i + 1;
9851                 surface = rsurface.modelsurfaces + surfacelist[i];
9852                 texture = surface->texture;
9853                 rsurface.texture = R_GetCurrentTexture(texture);
9854                 // scan ahead until we find a different texture
9855                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9856                 texturenumsurfaces = 0;
9857                 texturesurfacelist[texturenumsurfaces++] = surface;
9858                 if(FAKELIGHT_ENABLED)
9859                 {
9860                         rsurface.lightmaptexture = NULL;
9861                         rsurface.deluxemaptexture = NULL;
9862                         rsurface.uselightmaptexture = false;
9863                         for (;j < endsurface;j++)
9864                         {
9865                                 surface = rsurface.modelsurfaces + surfacelist[j];
9866                                 if (texture != surface->texture)
9867                                         break;
9868                                 texturesurfacelist[texturenumsurfaces++] = surface;
9869                         }
9870                 }
9871                 else
9872                 {
9873                         rsurface.lightmaptexture = surface->lightmaptexture;
9874                         rsurface.deluxemaptexture = surface->deluxemaptexture;
9875                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9876                         for (;j < endsurface;j++)
9877                         {
9878                                 surface = rsurface.modelsurfaces + surfacelist[j];
9879                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9880                                         break;
9881                                 texturesurfacelist[texturenumsurfaces++] = surface;
9882                         }
9883                 }
9884                 // render the range of surfaces
9885                 if (ent == r_refdef.scene.worldentity)
9886                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9887                 else
9888                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9889         }
9890         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9891 }
9892
9893 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9894 {
9895         // transparent surfaces get pushed off into the transparent queue
9896         int surfacelistindex;
9897         const msurface_t *surface;
9898         vec3_t tempcenter, center;
9899         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9900         {
9901                 surface = texturesurfacelist[surfacelistindex];
9902                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9903                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9904                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9905                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9906                 if (queueentity->transparent_offset) // transparent offset
9907                 {
9908                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9909                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9910                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9911                 }
9912                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9913         }
9914 }
9915
9916 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9917 {
9918         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9919                 return;
9920         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9921                 return;
9922         RSurf_SetupDepthAndCulling();
9923         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9924         if (rsurface.batchvertex3fbuffer)
9925                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9926         else
9927                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9928         RSurf_DrawBatch();
9929 }
9930
9931 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9932 {
9933         const entity_render_t *queueentity = r_refdef.scene.worldentity;
9934         CHECKGLERROR
9935         if (depthonly)
9936                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9937         else if (prepass)
9938         {
9939                 if (!rsurface.texture->currentnumlayers)
9940                         return;
9941                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9942                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9943                 else
9944                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9945         }
9946         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9947                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9948         else if (!rsurface.texture->currentnumlayers)
9949                 return;
9950         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9951         {
9952                 // in the deferred case, transparent surfaces were queued during prepass
9953                 if (!r_shadow_usingdeferredprepass)
9954                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9955         }
9956         else
9957         {
9958                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9959                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9960         }
9961         CHECKGLERROR
9962 }
9963
9964 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9965 {
9966         int i, j;
9967         texture_t *texture;
9968         R_FrameData_SetMark();
9969         // break the surface list down into batches by texture and use of lightmapping
9970         for (i = 0;i < numsurfaces;i = j)
9971         {
9972                 j = i + 1;
9973                 // texture is the base texture pointer, rsurface.texture is the
9974                 // current frame/skin the texture is directing us to use (for example
9975                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9976                 // use skin 1 instead)
9977                 texture = surfacelist[i]->texture;
9978                 rsurface.texture = R_GetCurrentTexture(texture);
9979                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
9980                 {
9981                         // if this texture is not the kind we want, skip ahead to the next one
9982                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9983                                 ;
9984                         continue;
9985                 }
9986                 if(FAKELIGHT_ENABLED || depthonly || prepass)
9987                 {
9988                         rsurface.lightmaptexture = NULL;
9989                         rsurface.deluxemaptexture = NULL;
9990                         rsurface.uselightmaptexture = false;
9991                         // simply scan ahead until we find a different texture or lightmap state
9992                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
9993                                 ;
9994                 }
9995                 else
9996                 {
9997                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
9998                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
9999                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10000                         // simply scan ahead until we find a different texture or lightmap state
10001                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10002                                 ;
10003                 }
10004                 // render the range of surfaces
10005                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10006         }
10007         R_FrameData_ReturnToMark();
10008 }
10009
10010 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10011 {
10012         CHECKGLERROR
10013         if (depthonly)
10014                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10015         else if (prepass)
10016         {
10017                 if (!rsurface.texture->currentnumlayers)
10018                         return;
10019                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10020                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10021                 else
10022                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10023         }
10024         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10025                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10026         else if (!rsurface.texture->currentnumlayers)
10027                 return;
10028         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10029         {
10030                 // in the deferred case, transparent surfaces were queued during prepass
10031                 if (!r_shadow_usingdeferredprepass)
10032                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10033         }
10034         else
10035         {
10036                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10037                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10038         }
10039         CHECKGLERROR
10040 }
10041
10042 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10043 {
10044         int i, j;
10045         texture_t *texture;
10046         R_FrameData_SetMark();
10047         // break the surface list down into batches by texture and use of lightmapping
10048         for (i = 0;i < numsurfaces;i = j)
10049         {
10050                 j = i + 1;
10051                 // texture is the base texture pointer, rsurface.texture is the
10052                 // current frame/skin the texture is directing us to use (for example
10053                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10054                 // use skin 1 instead)
10055                 texture = surfacelist[i]->texture;
10056                 rsurface.texture = R_GetCurrentTexture(texture);
10057                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10058                 {
10059                         // if this texture is not the kind we want, skip ahead to the next one
10060                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10061                                 ;
10062                         continue;
10063                 }
10064                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10065                 {
10066                         rsurface.lightmaptexture = NULL;
10067                         rsurface.deluxemaptexture = NULL;
10068                         rsurface.uselightmaptexture = false;
10069                         // simply scan ahead until we find a different texture or lightmap state
10070                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10071                                 ;
10072                 }
10073                 else
10074                 {
10075                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10076                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10077                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10078                         // simply scan ahead until we find a different texture or lightmap state
10079                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10080                                 ;
10081                 }
10082                 // render the range of surfaces
10083                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10084         }
10085         R_FrameData_ReturnToMark();
10086 }
10087
10088 float locboxvertex3f[6*4*3] =
10089 {
10090         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10091         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10092         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10093         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10094         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10095         1,0,0, 0,0,0, 0,1,0, 1,1,0
10096 };
10097
10098 unsigned short locboxelements[6*2*3] =
10099 {
10100          0, 1, 2, 0, 2, 3,
10101          4, 5, 6, 4, 6, 7,
10102          8, 9,10, 8,10,11,
10103         12,13,14, 12,14,15,
10104         16,17,18, 16,18,19,
10105         20,21,22, 20,22,23
10106 };
10107
10108 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10109 {
10110         int i, j;
10111         cl_locnode_t *loc = (cl_locnode_t *)ent;
10112         vec3_t mins, size;
10113         float vertex3f[6*4*3];
10114         CHECKGLERROR
10115         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10116         GL_DepthMask(false);
10117         GL_DepthRange(0, 1);
10118         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10119         GL_DepthTest(true);
10120         GL_CullFace(GL_NONE);
10121         R_EntityMatrix(&identitymatrix);
10122
10123 //      R_Mesh_ResetTextureState();
10124
10125         i = surfacelist[0];
10126         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10127                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10128                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10129                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10130
10131         if (VectorCompare(loc->mins, loc->maxs))
10132         {
10133                 VectorSet(size, 2, 2, 2);
10134                 VectorMA(loc->mins, -0.5f, size, mins);
10135         }
10136         else
10137         {
10138                 VectorCopy(loc->mins, mins);
10139                 VectorSubtract(loc->maxs, loc->mins, size);
10140         }
10141
10142         for (i = 0;i < 6*4*3;)
10143                 for (j = 0;j < 3;j++, i++)
10144                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10145
10146         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10147         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10148         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10149 }
10150
10151 void R_DrawLocs(void)
10152 {
10153         int index;
10154         cl_locnode_t *loc, *nearestloc;
10155         vec3_t center;
10156         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10157         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10158         {
10159                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10160                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10161         }
10162 }
10163
10164 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10165 {
10166         if (decalsystem->decals)
10167                 Mem_Free(decalsystem->decals);
10168         memset(decalsystem, 0, sizeof(*decalsystem));
10169 }
10170
10171 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)
10172 {
10173         tridecal_t *decal;
10174         tridecal_t *decals;
10175         int i;
10176
10177         // expand or initialize the system
10178         if (decalsystem->maxdecals <= decalsystem->numdecals)
10179         {
10180                 decalsystem_t old = *decalsystem;
10181                 qboolean useshortelements;
10182                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10183                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10184                 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)));
10185                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10186                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10187                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10188                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10189                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10190                 if (decalsystem->numdecals)
10191                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10192                 if (old.decals)
10193                         Mem_Free(old.decals);
10194                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10195                         decalsystem->element3i[i] = i;
10196                 if (useshortelements)
10197                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10198                                 decalsystem->element3s[i] = i;
10199         }
10200
10201         // grab a decal and search for another free slot for the next one
10202         decals = decalsystem->decals;
10203         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10204         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10205                 ;
10206         decalsystem->freedecal = i;
10207         if (decalsystem->numdecals <= i)
10208                 decalsystem->numdecals = i + 1;
10209
10210         // initialize the decal
10211         decal->lived = 0;
10212         decal->triangleindex = triangleindex;
10213         decal->surfaceindex = surfaceindex;
10214         decal->decalsequence = decalsequence;
10215         decal->color4f[0][0] = c0[0];
10216         decal->color4f[0][1] = c0[1];
10217         decal->color4f[0][2] = c0[2];
10218         decal->color4f[0][3] = 1;
10219         decal->color4f[1][0] = c1[0];
10220         decal->color4f[1][1] = c1[1];
10221         decal->color4f[1][2] = c1[2];
10222         decal->color4f[1][3] = 1;
10223         decal->color4f[2][0] = c2[0];
10224         decal->color4f[2][1] = c2[1];
10225         decal->color4f[2][2] = c2[2];
10226         decal->color4f[2][3] = 1;
10227         decal->vertex3f[0][0] = v0[0];
10228         decal->vertex3f[0][1] = v0[1];
10229         decal->vertex3f[0][2] = v0[2];
10230         decal->vertex3f[1][0] = v1[0];
10231         decal->vertex3f[1][1] = v1[1];
10232         decal->vertex3f[1][2] = v1[2];
10233         decal->vertex3f[2][0] = v2[0];
10234         decal->vertex3f[2][1] = v2[1];
10235         decal->vertex3f[2][2] = v2[2];
10236         decal->texcoord2f[0][0] = t0[0];
10237         decal->texcoord2f[0][1] = t0[1];
10238         decal->texcoord2f[1][0] = t1[0];
10239         decal->texcoord2f[1][1] = t1[1];
10240         decal->texcoord2f[2][0] = t2[0];
10241         decal->texcoord2f[2][1] = t2[1];
10242 }
10243
10244 extern cvar_t cl_decals_bias;
10245 extern cvar_t cl_decals_models;
10246 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10247 // baseparms, parms, temps
10248 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)
10249 {
10250         int cornerindex;
10251         int index;
10252         float v[9][3];
10253         const float *vertex3f;
10254         const float *normal3f;
10255         int numpoints;
10256         float points[2][9][3];
10257         float temp[3];
10258         float tc[9][2];
10259         float f;
10260         float c[9][4];
10261         const int *e;
10262
10263         e = rsurface.modelelement3i + 3*triangleindex;
10264
10265         vertex3f = rsurface.modelvertex3f;
10266         normal3f = rsurface.modelnormal3f;
10267
10268         for (cornerindex = 0;cornerindex < 3;cornerindex++)
10269         {
10270                 index = 3*e[cornerindex];
10271                 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10272         }
10273         // cull backfaces
10274         //TriangleNormal(v[0], v[1], v[2], normal);
10275         //if (DotProduct(normal, localnormal) < 0.0f)
10276         //      continue;
10277         // clip by each of the box planes formed from the projection matrix
10278         // if anything survives, we emit the decal
10279         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]);
10280         if (numpoints < 3)
10281                 return;
10282         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]);
10283         if (numpoints < 3)
10284                 return;
10285         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]);
10286         if (numpoints < 3)
10287                 return;
10288         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]);
10289         if (numpoints < 3)
10290                 return;
10291         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]);
10292         if (numpoints < 3)
10293                 return;
10294         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]);
10295         if (numpoints < 3)
10296                 return;
10297         // some part of the triangle survived, so we have to accept it...
10298         if (dynamic)
10299         {
10300                 // dynamic always uses the original triangle
10301                 numpoints = 3;
10302                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10303                 {
10304                         index = 3*e[cornerindex];
10305                         VectorCopy(vertex3f + index, v[cornerindex]);
10306                 }
10307         }
10308         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10309         {
10310                 // convert vertex positions to texcoords
10311                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10312                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10313                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10314                 // calculate distance fade from the projection origin
10315                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10316                 f = bound(0.0f, f, 1.0f);
10317                 c[cornerindex][0] = r * f;
10318                 c[cornerindex][1] = g * f;
10319                 c[cornerindex][2] = b * f;
10320                 c[cornerindex][3] = 1.0f;
10321                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10322         }
10323         if (dynamic)
10324                 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);
10325         else
10326                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10327                         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);
10328 }
10329 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)
10330 {
10331         matrix4x4_t projection;
10332         decalsystem_t *decalsystem;
10333         qboolean dynamic;
10334         dp_model_t *model;
10335         const msurface_t *surface;
10336         const msurface_t *surfaces;
10337         const int *surfacelist;
10338         const texture_t *texture;
10339         int numtriangles;
10340         int numsurfacelist;
10341         int surfacelistindex;
10342         int surfaceindex;
10343         int triangleindex;
10344         float localorigin[3];
10345         float localnormal[3];
10346         float localmins[3];
10347         float localmaxs[3];
10348         float localsize;
10349         //float normal[3];
10350         float planes[6][4];
10351         float angles[3];
10352         bih_t *bih;
10353         int bih_triangles_count;
10354         int bih_triangles[256];
10355         int bih_surfaces[256];
10356
10357         decalsystem = &ent->decalsystem;
10358         model = ent->model;
10359         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10360         {
10361                 R_DecalSystem_Reset(&ent->decalsystem);
10362                 return;
10363         }
10364
10365         if (!model->brush.data_leafs && !cl_decals_models.integer)
10366         {
10367                 if (decalsystem->model)
10368                         R_DecalSystem_Reset(decalsystem);
10369                 return;
10370         }
10371
10372         if (decalsystem->model != model)
10373                 R_DecalSystem_Reset(decalsystem);
10374         decalsystem->model = model;
10375
10376         RSurf_ActiveModelEntity(ent, true, false, false);
10377
10378         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10379         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10380         VectorNormalize(localnormal);
10381         localsize = worldsize*rsurface.inversematrixscale;
10382         localmins[0] = localorigin[0] - localsize;
10383         localmins[1] = localorigin[1] - localsize;
10384         localmins[2] = localorigin[2] - localsize;
10385         localmaxs[0] = localorigin[0] + localsize;
10386         localmaxs[1] = localorigin[1] + localsize;
10387         localmaxs[2] = localorigin[2] + localsize;
10388
10389         //VectorCopy(localnormal, planes[4]);
10390         //VectorVectors(planes[4], planes[2], planes[0]);
10391         AnglesFromVectors(angles, localnormal, NULL, false);
10392         AngleVectors(angles, planes[0], planes[2], planes[4]);
10393         VectorNegate(planes[0], planes[1]);
10394         VectorNegate(planes[2], planes[3]);
10395         VectorNegate(planes[4], planes[5]);
10396         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10397         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10398         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10399         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10400         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10401         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10402
10403 #if 1
10404 // works
10405 {
10406         matrix4x4_t forwardprojection;
10407         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10408         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10409 }
10410 #else
10411 // broken
10412 {
10413         float projectionvector[4][3];
10414         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10415         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10416         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10417         projectionvector[0][0] = planes[0][0] * ilocalsize;
10418         projectionvector[0][1] = planes[1][0] * ilocalsize;
10419         projectionvector[0][2] = planes[2][0] * ilocalsize;
10420         projectionvector[1][0] = planes[0][1] * ilocalsize;
10421         projectionvector[1][1] = planes[1][1] * ilocalsize;
10422         projectionvector[1][2] = planes[2][1] * ilocalsize;
10423         projectionvector[2][0] = planes[0][2] * ilocalsize;
10424         projectionvector[2][1] = planes[1][2] * ilocalsize;
10425         projectionvector[2][2] = planes[2][2] * ilocalsize;
10426         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10427         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10428         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10429         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10430 }
10431 #endif
10432
10433         dynamic = model->surfmesh.isanimated;
10434         numsurfacelist = model->nummodelsurfaces;
10435         surfacelist = model->sortedmodelsurfaces;
10436         surfaces = model->data_surfaces;
10437
10438         bih = NULL;
10439         bih_triangles_count = -1;
10440         if(!dynamic)
10441         {
10442                 if(model->render_bih.numleafs)
10443                         bih = &model->render_bih;
10444                 else if(model->collision_bih.numleafs)
10445                         bih = &model->collision_bih;
10446         }
10447         if(bih)
10448                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10449         if(bih_triangles_count == 0)
10450                 return;
10451         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10452                 return;
10453         if(bih_triangles_count > 0)
10454         {
10455                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10456                 {
10457                         surfaceindex = bih_surfaces[triangleindex];
10458                         surface = surfaces + surfaceindex;
10459                         texture = surface->texture;
10460                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10461                                 continue;
10462                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10463                                 continue;
10464                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10465                 }
10466         }
10467         else
10468         {
10469                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10470                 {
10471                         surfaceindex = surfacelist[surfacelistindex];
10472                         surface = surfaces + surfaceindex;
10473                         // check cull box first because it rejects more than any other check
10474                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10475                                 continue;
10476                         // skip transparent surfaces
10477                         texture = surface->texture;
10478                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10479                                 continue;
10480                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10481                                 continue;
10482                         numtriangles = surface->num_triangles;
10483                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10484                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10485                 }
10486         }
10487 }
10488
10489 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10490 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)
10491 {
10492         int renderentityindex;
10493         float worldmins[3];
10494         float worldmaxs[3];
10495         entity_render_t *ent;
10496
10497         if (!cl_decals_newsystem.integer)
10498                 return;
10499
10500         worldmins[0] = worldorigin[0] - worldsize;
10501         worldmins[1] = worldorigin[1] - worldsize;
10502         worldmins[2] = worldorigin[2] - worldsize;
10503         worldmaxs[0] = worldorigin[0] + worldsize;
10504         worldmaxs[1] = worldorigin[1] + worldsize;
10505         worldmaxs[2] = worldorigin[2] + worldsize;
10506
10507         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10508
10509         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10510         {
10511                 ent = r_refdef.scene.entities[renderentityindex];
10512                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10513                         continue;
10514
10515                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10516         }
10517 }
10518
10519 typedef struct r_decalsystem_splatqueue_s
10520 {
10521         vec3_t worldorigin;
10522         vec3_t worldnormal;
10523         float color[4];
10524         float tcrange[4];
10525         float worldsize;
10526         int decalsequence;
10527 }
10528 r_decalsystem_splatqueue_t;
10529
10530 int r_decalsystem_numqueued = 0;
10531 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10532
10533 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)
10534 {
10535         r_decalsystem_splatqueue_t *queue;
10536
10537         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10538                 return;
10539
10540         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10541         VectorCopy(worldorigin, queue->worldorigin);
10542         VectorCopy(worldnormal, queue->worldnormal);
10543         Vector4Set(queue->color, r, g, b, a);
10544         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10545         queue->worldsize = worldsize;
10546         queue->decalsequence = cl.decalsequence++;
10547 }
10548
10549 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10550 {
10551         int i;
10552         r_decalsystem_splatqueue_t *queue;
10553
10554         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10555                 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);
10556         r_decalsystem_numqueued = 0;
10557 }
10558
10559 extern cvar_t cl_decals_max;
10560 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10561 {
10562         int i;
10563         decalsystem_t *decalsystem = &ent->decalsystem;
10564         int numdecals;
10565         int killsequence;
10566         tridecal_t *decal;
10567         float frametime;
10568         float lifetime;
10569
10570         if (!decalsystem->numdecals)
10571                 return;
10572
10573         if (r_showsurfaces.integer)
10574                 return;
10575
10576         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10577         {
10578                 R_DecalSystem_Reset(decalsystem);
10579                 return;
10580         }
10581
10582         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10583         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10584
10585         if (decalsystem->lastupdatetime)
10586                 frametime = (cl.time - decalsystem->lastupdatetime);
10587         else
10588                 frametime = 0;
10589         decalsystem->lastupdatetime = cl.time;
10590         decal = decalsystem->decals;
10591         numdecals = decalsystem->numdecals;
10592
10593         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10594         {
10595                 if (decal->color4f[0][3])
10596                 {
10597                         decal->lived += frametime;
10598                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10599                         {
10600                                 memset(decal, 0, sizeof(*decal));
10601                                 if (decalsystem->freedecal > i)
10602                                         decalsystem->freedecal = i;
10603                         }
10604                 }
10605         }
10606         decal = decalsystem->decals;
10607         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10608                 numdecals--;
10609
10610         // collapse the array by shuffling the tail decals into the gaps
10611         for (;;)
10612         {
10613                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10614                         decalsystem->freedecal++;
10615                 if (decalsystem->freedecal == numdecals)
10616                         break;
10617                 decal[decalsystem->freedecal] = decal[--numdecals];
10618         }
10619
10620         decalsystem->numdecals = numdecals;
10621
10622         if (numdecals <= 0)
10623         {
10624                 // if there are no decals left, reset decalsystem
10625                 R_DecalSystem_Reset(decalsystem);
10626         }
10627 }
10628
10629 extern skinframe_t *decalskinframe;
10630 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10631 {
10632         int i;
10633         decalsystem_t *decalsystem = &ent->decalsystem;
10634         int numdecals;
10635         tridecal_t *decal;
10636         float faderate;
10637         float alpha;
10638         float *v3f;
10639         float *c4f;
10640         float *t2f;
10641         const int *e;
10642         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10643         int numtris = 0;
10644
10645         numdecals = decalsystem->numdecals;
10646         if (!numdecals)
10647                 return;
10648
10649         if (r_showsurfaces.integer)
10650                 return;
10651
10652         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10653         {
10654                 R_DecalSystem_Reset(decalsystem);
10655                 return;
10656         }
10657
10658         // if the model is static it doesn't matter what value we give for
10659         // wantnormals and wanttangents, so this logic uses only rules applicable
10660         // to a model, knowing that they are meaningless otherwise
10661         if (ent == r_refdef.scene.worldentity)
10662                 RSurf_ActiveWorldEntity();
10663         else
10664                 RSurf_ActiveModelEntity(ent, false, false, false);
10665
10666         decalsystem->lastupdatetime = cl.time;
10667         decal = decalsystem->decals;
10668
10669         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10670
10671         // update vertex positions for animated models
10672         v3f = decalsystem->vertex3f;
10673         c4f = decalsystem->color4f;
10674         t2f = decalsystem->texcoord2f;
10675         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10676         {
10677                 if (!decal->color4f[0][3])
10678                         continue;
10679
10680                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10681                         continue;
10682
10683                 // update color values for fading decals
10684                 if (decal->lived >= cl_decals_time.value)
10685                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10686                 else
10687                         alpha = 1.0f;
10688
10689                 c4f[ 0] = decal->color4f[0][0] * alpha;
10690                 c4f[ 1] = decal->color4f[0][1] * alpha;
10691                 c4f[ 2] = decal->color4f[0][2] * alpha;
10692                 c4f[ 3] = 1;
10693                 c4f[ 4] = decal->color4f[1][0] * alpha;
10694                 c4f[ 5] = decal->color4f[1][1] * alpha;
10695                 c4f[ 6] = decal->color4f[1][2] * alpha;
10696                 c4f[ 7] = 1;
10697                 c4f[ 8] = decal->color4f[2][0] * alpha;
10698                 c4f[ 9] = decal->color4f[2][1] * alpha;
10699                 c4f[10] = decal->color4f[2][2] * alpha;
10700                 c4f[11] = 1;
10701
10702                 t2f[0] = decal->texcoord2f[0][0];
10703                 t2f[1] = decal->texcoord2f[0][1];
10704                 t2f[2] = decal->texcoord2f[1][0];
10705                 t2f[3] = decal->texcoord2f[1][1];
10706                 t2f[4] = decal->texcoord2f[2][0];
10707                 t2f[5] = decal->texcoord2f[2][1];
10708
10709                 // update vertex positions for animated models
10710                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10711                 {
10712                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10713                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10714                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10715                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10716                 }
10717                 else
10718                 {
10719                         VectorCopy(decal->vertex3f[0], v3f);
10720                         VectorCopy(decal->vertex3f[1], v3f + 3);
10721                         VectorCopy(decal->vertex3f[2], v3f + 6);
10722                 }
10723
10724                 if (r_refdef.fogenabled)
10725                 {
10726                         alpha = RSurf_FogVertex(v3f);
10727                         VectorScale(c4f, alpha, c4f);
10728                         alpha = RSurf_FogVertex(v3f + 3);
10729                         VectorScale(c4f + 4, alpha, c4f + 4);
10730                         alpha = RSurf_FogVertex(v3f + 6);
10731                         VectorScale(c4f + 8, alpha, c4f + 8);
10732                 }
10733
10734                 v3f += 9;
10735                 c4f += 12;
10736                 t2f += 6;
10737                 numtris++;
10738         }
10739
10740         if (numtris > 0)
10741         {
10742                 r_refdef.stats.drawndecals += numtris;
10743
10744                 // now render the decals all at once
10745                 // (this assumes they all use one particle font texture!)
10746                 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);
10747 //              R_Mesh_ResetTextureState();
10748                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10749                 GL_DepthMask(false);
10750                 GL_DepthRange(0, 1);
10751                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10752                 GL_DepthTest(true);
10753                 GL_CullFace(GL_NONE);
10754                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10755                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10756                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10757         }
10758 }
10759
10760 static void R_DrawModelDecals(void)
10761 {
10762         int i, numdecals;
10763
10764         // fade faster when there are too many decals
10765         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10766         for (i = 0;i < r_refdef.scene.numentities;i++)
10767                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10768
10769         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10770         for (i = 0;i < r_refdef.scene.numentities;i++)
10771                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10772                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10773
10774         R_DecalSystem_ApplySplatEntitiesQueue();
10775
10776         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10777         for (i = 0;i < r_refdef.scene.numentities;i++)
10778                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10779
10780         r_refdef.stats.totaldecals += numdecals;
10781
10782         if (r_showsurfaces.integer)
10783                 return;
10784
10785         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10786
10787         for (i = 0;i < r_refdef.scene.numentities;i++)
10788         {
10789                 if (!r_refdef.viewcache.entityvisible[i])
10790                         continue;
10791                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10792                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10793         }
10794 }
10795
10796 extern cvar_t mod_collision_bih;
10797 void R_DrawDebugModel(void)
10798 {
10799         entity_render_t *ent = rsurface.entity;
10800         int i, j, k, l, flagsmask;
10801         const msurface_t *surface;
10802         dp_model_t *model = ent->model;
10803         vec3_t v;
10804
10805         switch(vid.renderpath)
10806         {
10807         case RENDERPATH_GL11:
10808         case RENDERPATH_GL13:
10809         case RENDERPATH_GL20:
10810                 break;
10811         case RENDERPATH_D3D9:
10812                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10813                 return;
10814         case RENDERPATH_D3D10:
10815                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10816                 return;
10817         case RENDERPATH_D3D11:
10818                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10819                 return;
10820         case RENDERPATH_SOFT:
10821                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10822                 return;
10823         case RENDERPATH_GLES2:
10824                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10825                 return;
10826         }
10827
10828         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10829
10830 //      R_Mesh_ResetTextureState();
10831         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10832         GL_DepthRange(0, 1);
10833         GL_DepthTest(!r_showdisabledepthtest.integer);
10834         GL_DepthMask(false);
10835         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10836
10837         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10838         {
10839                 int triangleindex;
10840                 int bihleafindex;
10841                 qboolean cullbox = ent == r_refdef.scene.worldentity;
10842                 const q3mbrush_t *brush;
10843                 const bih_t *bih = &model->collision_bih;
10844                 const bih_leaf_t *bihleaf;
10845                 float vertex3f[3][3];
10846                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10847                 cullbox = false;
10848                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10849                 {
10850                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10851                                 continue;
10852                         switch (bihleaf->type)
10853                         {
10854                         case BIH_BRUSH:
10855                                 brush = model->brush.data_brushes + bihleaf->itemindex;
10856                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
10857                                 {
10858                                         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);
10859                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10860                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10861                                 }
10862                                 break;
10863                         case BIH_COLLISIONTRIANGLE:
10864                                 triangleindex = bihleaf->itemindex;
10865                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10866                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10867                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10868                                 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);
10869                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10870                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10871                                 break;
10872                         case BIH_RENDERTRIANGLE:
10873                                 triangleindex = bihleaf->itemindex;
10874                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10875                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10876                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10877                                 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);
10878                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10879                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10880                                 break;
10881                         }
10882                 }
10883         }
10884
10885         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10886
10887         if (r_showtris.integer || (r_shownormals.value != 0))
10888         {
10889                 if (r_showdisabledepthtest.integer)
10890                 {
10891                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10892                         GL_DepthMask(false);
10893                 }
10894                 else
10895                 {
10896                         GL_BlendFunc(GL_ONE, GL_ZERO);
10897                         GL_DepthMask(true);
10898                 }
10899                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10900                 {
10901                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10902                                 continue;
10903                         rsurface.texture = R_GetCurrentTexture(surface->texture);
10904                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10905                         {
10906                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10907                                 if (r_showtris.value > 0)
10908                                 {
10909                                         if (!rsurface.texture->currentlayers->depthmask)
10910                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10911                                         else if (ent == r_refdef.scene.worldentity)
10912                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10913                                         else
10914                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10915                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10916                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10917                                         RSurf_DrawBatch();
10918                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10919                                         CHECKGLERROR
10920                                 }
10921                                 if (r_shownormals.value < 0)
10922                                 {
10923                                         qglBegin(GL_LINES);
10924                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10925                                         {
10926                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10927                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10928                                                 qglVertex3f(v[0], v[1], v[2]);
10929                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10930                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10931                                                 qglVertex3f(v[0], v[1], v[2]);
10932                                         }
10933                                         qglEnd();
10934                                         CHECKGLERROR
10935                                 }
10936                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10937                                 {
10938                                         qglBegin(GL_LINES);
10939                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10940                                         {
10941                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10942                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10943                                                 qglVertex3f(v[0], v[1], v[2]);
10944                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10945                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10946                                                 qglVertex3f(v[0], v[1], v[2]);
10947                                         }
10948                                         qglEnd();
10949                                         CHECKGLERROR
10950                                         qglBegin(GL_LINES);
10951                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10952                                         {
10953                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10954                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10955                                                 qglVertex3f(v[0], v[1], v[2]);
10956                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10957                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10958                                                 qglVertex3f(v[0], v[1], v[2]);
10959                                         }
10960                                         qglEnd();
10961                                         CHECKGLERROR
10962                                         qglBegin(GL_LINES);
10963                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10964                                         {
10965                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10966                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10967                                                 qglVertex3f(v[0], v[1], v[2]);
10968                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10969                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10970                                                 qglVertex3f(v[0], v[1], v[2]);
10971                                         }
10972                                         qglEnd();
10973                                         CHECKGLERROR
10974                                 }
10975                         }
10976                 }
10977                 rsurface.texture = NULL;
10978         }
10979 }
10980
10981 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
10982 int r_maxsurfacelist = 0;
10983 const msurface_t **r_surfacelist = NULL;
10984 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
10985 {
10986         int i, j, endj, flagsmask;
10987         dp_model_t *model = r_refdef.scene.worldmodel;
10988         msurface_t *surfaces;
10989         unsigned char *update;
10990         int numsurfacelist = 0;
10991         if (model == NULL)
10992                 return;
10993
10994         if (r_maxsurfacelist < model->num_surfaces)
10995         {
10996                 r_maxsurfacelist = model->num_surfaces;
10997                 if (r_surfacelist)
10998                         Mem_Free((msurface_t**)r_surfacelist);
10999                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11000         }
11001
11002         RSurf_ActiveWorldEntity();
11003
11004         surfaces = model->data_surfaces;
11005         update = model->brushq1.lightmapupdateflags;
11006
11007         // update light styles on this submodel
11008         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11009         {
11010                 model_brush_lightstyleinfo_t *style;
11011                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11012                 {
11013                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11014                         {
11015                                 int *list = style->surfacelist;
11016                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11017                                 for (j = 0;j < style->numsurfaces;j++)
11018                                         update[list[j]] = true;
11019                         }
11020                 }
11021         }
11022
11023         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11024
11025         if (debug)
11026         {
11027                 R_DrawDebugModel();
11028                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11029                 return;
11030         }
11031
11032         rsurface.lightmaptexture = NULL;
11033         rsurface.deluxemaptexture = NULL;
11034         rsurface.uselightmaptexture = false;
11035         rsurface.texture = NULL;
11036         rsurface.rtlight = NULL;
11037         numsurfacelist = 0;
11038         // add visible surfaces to draw list
11039         for (i = 0;i < model->nummodelsurfaces;i++)
11040         {
11041                 j = model->sortedmodelsurfaces[i];
11042                 if (r_refdef.viewcache.world_surfacevisible[j])
11043                         r_surfacelist[numsurfacelist++] = surfaces + j;
11044         }
11045         // update lightmaps if needed
11046         if (model->brushq1.firstrender)
11047         {
11048                 model->brushq1.firstrender = false;
11049                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11050                         if (update[j])
11051                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11052         }
11053         else if (update)
11054         {
11055                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11056                         if (r_refdef.viewcache.world_surfacevisible[j])
11057                                 if (update[j])
11058                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11059         }
11060         // don't do anything if there were no surfaces
11061         if (!numsurfacelist)
11062         {
11063                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11064                 return;
11065         }
11066         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11067
11068         // add to stats if desired
11069         if (r_speeds.integer && !skysurfaces && !depthonly)
11070         {
11071                 r_refdef.stats.world_surfaces += numsurfacelist;
11072                 for (j = 0;j < numsurfacelist;j++)
11073                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11074         }
11075
11076         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11077 }
11078
11079 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11080 {
11081         int i, j, endj, flagsmask;
11082         dp_model_t *model = ent->model;
11083         msurface_t *surfaces;
11084         unsigned char *update;
11085         int numsurfacelist = 0;
11086         if (model == NULL)
11087                 return;
11088
11089         if (r_maxsurfacelist < model->num_surfaces)
11090         {
11091                 r_maxsurfacelist = model->num_surfaces;
11092                 if (r_surfacelist)
11093                         Mem_Free((msurface_t **)r_surfacelist);
11094                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11095         }
11096
11097         // if the model is static it doesn't matter what value we give for
11098         // wantnormals and wanttangents, so this logic uses only rules applicable
11099         // to a model, knowing that they are meaningless otherwise
11100         if (ent == r_refdef.scene.worldentity)
11101                 RSurf_ActiveWorldEntity();
11102         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11103                 RSurf_ActiveModelEntity(ent, false, false, false);
11104         else if (prepass)
11105                 RSurf_ActiveModelEntity(ent, true, true, true);
11106         else if (depthonly)
11107         {
11108                 switch (vid.renderpath)
11109                 {
11110                 case RENDERPATH_GL20:
11111                 case RENDERPATH_D3D9:
11112                 case RENDERPATH_D3D10:
11113                 case RENDERPATH_D3D11:
11114                 case RENDERPATH_SOFT:
11115                 case RENDERPATH_GLES2:
11116                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11117                         break;
11118                 case RENDERPATH_GL13:
11119                 case RENDERPATH_GL11:
11120                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11121                         break;
11122                 }
11123         }
11124         else
11125         {
11126                 switch (vid.renderpath)
11127                 {
11128                 case RENDERPATH_GL20:
11129                 case RENDERPATH_D3D9:
11130                 case RENDERPATH_D3D10:
11131                 case RENDERPATH_D3D11:
11132                 case RENDERPATH_SOFT:
11133                 case RENDERPATH_GLES2:
11134                         RSurf_ActiveModelEntity(ent, true, true, false);
11135                         break;
11136                 case RENDERPATH_GL13:
11137                 case RENDERPATH_GL11:
11138                         RSurf_ActiveModelEntity(ent, true, false, false);
11139                         break;
11140                 }
11141         }
11142
11143         surfaces = model->data_surfaces;
11144         update = model->brushq1.lightmapupdateflags;
11145
11146         // update light styles
11147         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11148         {
11149                 model_brush_lightstyleinfo_t *style;
11150                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11151                 {
11152                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11153                         {
11154                                 int *list = style->surfacelist;
11155                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11156                                 for (j = 0;j < style->numsurfaces;j++)
11157                                         update[list[j]] = true;
11158                         }
11159                 }
11160         }
11161
11162         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11163
11164         if (debug)
11165         {
11166                 R_DrawDebugModel();
11167                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11168                 return;
11169         }
11170
11171         rsurface.lightmaptexture = NULL;
11172         rsurface.deluxemaptexture = NULL;
11173         rsurface.uselightmaptexture = false;
11174         rsurface.texture = NULL;
11175         rsurface.rtlight = NULL;
11176         numsurfacelist = 0;
11177         // add visible surfaces to draw list
11178         for (i = 0;i < model->nummodelsurfaces;i++)
11179                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11180         // don't do anything if there were no surfaces
11181         if (!numsurfacelist)
11182         {
11183                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11184                 return;
11185         }
11186         // update lightmaps if needed
11187         if (update)
11188         {
11189                 int updated = 0;
11190                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11191                 {
11192                         if (update[j])
11193                         {
11194                                 updated++;
11195                                 R_BuildLightMap(ent, surfaces + j);
11196                         }
11197                 }
11198         }
11199         if (update)
11200                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11201                         if (update[j])
11202                                 R_BuildLightMap(ent, surfaces + j);
11203         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11204
11205         // add to stats if desired
11206         if (r_speeds.integer && !skysurfaces && !depthonly)
11207         {
11208                 r_refdef.stats.entities_surfaces += numsurfacelist;
11209                 for (j = 0;j < numsurfacelist;j++)
11210                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11211         }
11212
11213         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11214 }
11215
11216 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11217 {
11218         static texture_t texture;
11219         static msurface_t surface;
11220         const msurface_t *surfacelist = &surface;
11221
11222         // fake enough texture and surface state to render this geometry
11223
11224         texture.update_lastrenderframe = -1; // regenerate this texture
11225         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11226         texture.currentskinframe = skinframe;
11227         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11228         texture.offsetmapping = OFFSETMAPPING_OFF;
11229         texture.offsetscale = 1;
11230         texture.specularscalemod = 1;
11231         texture.specularpowermod = 1;
11232
11233         surface.texture = &texture;
11234         surface.num_triangles = numtriangles;
11235         surface.num_firsttriangle = firsttriangle;
11236         surface.num_vertices = numvertices;
11237         surface.num_firstvertex = firstvertex;
11238
11239         // now render it
11240         rsurface.texture = R_GetCurrentTexture(surface.texture);
11241         rsurface.lightmaptexture = NULL;
11242         rsurface.deluxemaptexture = NULL;
11243         rsurface.uselightmaptexture = false;
11244         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11245 }
11246
11247 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)
11248 {
11249         static msurface_t surface;
11250         const msurface_t *surfacelist = &surface;
11251
11252         // fake enough texture and surface state to render this geometry
11253         surface.texture = texture;
11254         surface.num_triangles = numtriangles;
11255         surface.num_firsttriangle = firsttriangle;
11256         surface.num_vertices = numvertices;
11257         surface.num_firstvertex = firstvertex;
11258
11259         // now render it
11260         rsurface.texture = R_GetCurrentTexture(surface.texture);
11261         rsurface.lightmaptexture = NULL;
11262         rsurface.deluxemaptexture = NULL;
11263         rsurface.uselightmaptexture = false;
11264         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11265 }